<script>on mouseUpset the visible of field "source" to not the visible of field "source"if the visible of field "source" is true thenset the name of me to "Hide Pascal Source"else set the name of me to "Show Pascal Source"end mouseUp</script>
</part>
<content>
<layer>background</layer>
<id>16</id>
<text><span class="style1">INSTALL XCMD version 1.2</span><span class="style2">Kevin CalhounRInstall copies any resource contained in any currently open resource file to a file you specify by full pathname. It automatically removes from the target file any resource of the same type and name (or of the same type and resource ID) as the resource to be copied.INVOKING RINSTALLRInstall resType,resName,fileNameThe first parameter, resType, is that type of resource you want to install. The second parameter, resName, is the name of the resource you want to install. Or you can pass the id of the resource in this parameter by preceding it with a pound sign (ex. #123). The third parameter, fileName, is the full pathname of the file into which the resource is to be copied.If an error occurs, RInstall returns an error message, the first word of which is "Error".REVISION HISTORY30 April 1989 1.022 July 1989 No longer leaves a NIL master pointer behind when replacing a resource.10/27/92 version 1.2: If second parameter is a number starting with '#', use it as a resource id instead of a name. Also, set up for THINK Pascal 4.0.</span></text>
</content>
<content>
<layer>background</layer>
<id>36</id>
<text>unit RInstall;{ RInstall XCMD ©1989 by the Trustees of Dartmouth College }{ Written by Kevin Calhoun }{Modified 10/27/92 by Roger Brown version 1.2 }{Example for THINK C 4.0.}{If "name" parameter is a number preceded by a # character (ex. #123), use it as a resource ID instead of a name."}{For THINK Pascal 4.0, needs RSRCRuntime.lib, Interface.lin, HyperXLib.lib, HyperXCmd.p, SysEqu.p, Resources.P}{Type is XCMD, id 3128.}interface uses{Types, Memory, Events, Windows, Files, ToolUtils, Resources, SysEqu, Errors, HyperXCmd;} Resources, SysEqu, HyperXCmd; procedure Main (paramPtr: XCMDPtr);implementation procedure ResInstall (paramPtr: XCMDPtr); FORWARD; procedure Main (paramPtr: XCMDPtr); begin ResInstall(paramPtr); end; procedure PassReturnValue (paramPtr: XCMDPtr; theMsg: Str255); { set theResult and quit } begin paramPtr^.returnValue := PasToZero(paramPtr, theMsg); end; function MyOpenResFile (fileName: Str255; var refNum: INTEGER; var wasOpen: BOOLEAN): OSErr; type HandlePtr = ^Handle; var oldTopMapHndl: Handle; begin MyOpenResFile := noErr; oldTopMapHndl := HandlePtr(TopMapHndl)^; { remember current TopMapHndl } refNum := OpenResFile(fileName); { open resource file } if (refNum = -1) then { error opening file } begin MyOpenResFile := ResError; EXIT(MyOpenResFile); end else if (oldTopMapHndl = HandlePtr(TopMapHndl)^) then wasOpen := TRUE { no change -- it was open } else wasOpen := FALSE; { res file wasn't open before } end; procedure RemoveResource (rType: ResType; resID: INTEGER; name: Str255); var resAlready: Handle; begin SetResLoad(FALSE); repeat resAlready := Get1Resource(rType, resID); if resAlready <> nil then begin RmveResource(resAlready); DisposHandle(resAlready); end; until resAlready = nil; repeat resAlready := Get1NamedResource(rType, name); if resAlready <> nil then begin RmveResource(resAlready); DisposHandle(resAlready); end; until resAlready = nil; SetResLoad(TRUE); end; procedure ResInstall (paramPtr: XCMDPtr); label 99, 100; var err: OSErr; targetFile, curFile: INTEGER; str: Str255; rType: ResType; resource: Handle; resID: INTEGER; attrs: INTEGER; targetStack: Str255; wasOpen: BOOLEAN; numStr: Str31; tempID: longint; procedure SetReturnValue; begin if err <> noErr then begin NumToStr(paramPtr, err, str); PassReturnValue(paramPtr, CONCAT('Error ', str)); end; end; procedure BailOut; begin if resource <> nil then DisposHandle(resource); SetReturnValue; EXIT(ResInstall); end; begin err := noErr; resource := nil; curFile := CurResFile; if paramPtr^.paramCount < 3 then begin PassReturnValue(paramPtr, 'RInstall XCMD 1.1 ©1989 Dartmouth College'); Exit(ResInstall); end; BlockMove(paramPtr^.params[1]^, @rType, 4); ZeroToPas(paramPtr, paramPtr^.params[2]^, str); {RWB See if the name is really an ID number} if (length(str) < 31) and (str[1] = '#') then begin numStr := str; delete(str, 1, 1); tempID := StrToNum(paramPtr, numStr); if tempID <> 0 then begin resID := tempID; resource := GetResource(rType, resID); end; end else resource := GetNamedResource(rType, str); err := ResError; if err <> noErr then goto 100; GetResInfo(resource, resID, rType, str); err := ResError; if err <> noErr then BailOut; attrs := GetResAttrs(resource); err := HandToHand(resource); if err <> noErr then BailOut; MoveHHi(resource); HLock(resource); ZeroToPas(paramPtr, paramPtr^.params[3]^, targetStack); err := MyOpenResFile(targetStack, targetFile, wasOpen); if (targetFile = -1) and (err = eofErr) then begin wasOpen := FALSE; CreateResFile(targetStack); err := ResError; if err = noErr then targetFile := OpenResFile(targetStack); end; if (err <> noErr) or (targetFile = -1) then BailOut; UseResFile(targetFile); RemoveResource(rType, resID, str); AddResource(resource, rType, resID, str); err := ResError; if err <> noErr then begin DisposHandle(resource); goto 99; end; SetResAttrs(resource, attrs); ChangedResource(resource); WriteResource(resource); UpdateResFile(targetFile); err := ResError; if not wasOpen then CloseResFile(targetFile);99: UseResFile(curFile);100: SetReturnValue; end;end.</text>
<script>on mouseUpget GetFieldText( "cd fld sourceText" )if word 1 of it is not "Error" thenSetFieldText "cd fld destText", itDisposeFieldText itend ifend mouseUp</script>
</part>
<part>
<id>4</id>
<type>field</type>
<visible> <true /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <false /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <false /> </lockText>
<rect>
<left>328</left>
<top>51</top>
<right>482</right>
<bottom>127</bottom>
</rect>
<style>rectangle</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Geneva</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<textHeight>16</textHeight>
<name>sourceText</name>
<script></script>
</part>
<part>
<id>5</id>
<type>field</type>
<visible> <true /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <false /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>18</left>
<top>40</top>
<right>316</right>
<bottom>294</bottom>
</rect>
<style>scrolling</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <true /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Geneva</font>
<textSize>10</textSize>
<textStyle>plain</textStyle>
<textHeight>13</textHeight>
<name>Documentation</name>
<script></script>
</part>
<part>
<id>7</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>295</left>
<top>311</top>
<right>416</right>
<bottom>333</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Show C Source</name>
<script>on mouseUpget the visible of cd field "source"set the visible of cd field "source" to not itif it is false thenset the name of me to "Hide C Source"elseset the name of me to "Show C Source"end ifend mouseUp</script>
<text><span class="style1">etFieldText XFCN 1.0</span><span class="style2">Susan TenneyGetFieldText (XFCN), SetFieldText (XCMD), and DisposeFieldText (XCMD) are used together to copy the contents of a field into another field, keeping text styles intact. GetFieldText returns a handle to a copy of the styled text in a field. This handle can be passed to SetFieldText to set the text of another field. DisposeFieldText is used to release the memory used for the copy of the text. SetFieldText and DisposeFieldText are on the next cards.Syntax: GetFieldText( fldDescriptor )Parameters: fldDescriptor the source field descriptorReturns: A handle to a copy of the text in the field. (Note: This is not strictly a TEHandle, as it contains other information identifying it as returned from GetFieldText. Therefore it should be used only as a parameter to SetFieldText.)If an error occurs, returns an error message, the first word of which is "Error"Example: -- to copy styled text from card field 1 to card field 2: get GetFieldText( "cd field 1" ) SetFieldText "cd fld 2", it DisposeFieldText itNote that the quotes ARE necessary.</span></text>
</content>
<content>
<layer>background</layer>
<id>36</id>
<text>/* GetFieldText 1.0 © 1992 Trustees of Dartmouth College written in THINK C © 1991 Symantec Corporation by Susan Tenney, Dartmouth College Computing Services May, 199111/13/92 Roger Brown edited for THINK C 5.0.Returns styled text handle for a HyperCard field. Used in conjunction with SetFieldText to copy one field to another, keeping style information intact. Syntax: GetFieldText( fldDescriptor ) Returns: Handle to a copy of the styled text of the specified field. If there was an error, returns a message, the first word of which is "Error". Example: put GetFieldText( "fld someText" ) into thisText SetFieldText "fld someOtherText", thisText DisposeText( thisText ) Note that quotes are required around the field descriptor. Note also that once the text is no longer needed, its memory should be released with theDisposeText XCMD. To build the XFCN, create a Think C project with this, ANSI-A4,HyperXLib (callback library built for Think C), and MacTraps. Buildas code resource type XFCN with name GetFieldText.*/#include "HyperXCMD.h"#include "string.h"#include <SetUpA4.h>#define NIL 0L#define GFTID 40491L /* arbitrary ID */typedef struct { TEHandle TEH ; long myID ;} GFTInfo, **GFTHandle ;TEHandle GetFieldTextHandle() ;/* Global Variables */XCmdPtr gParamPtr ;Boolean gError ;/* procedures */void GetHCWord( char *inStr, int wordNum, char *outStr, Boolean *error ); pascal void main( paramPtr )XCmdPtr paramPtr ;{ RememberA0(); SetUpA4(); gParamPtr = paramPtr ; DoMyStuff() ; RestoreA4();}DoMyStuff(){ GFTHandle returnHandle ; TEHandle TEH ; Str255 handleStr ; gError = false ; returnHandle = (GFTHandle) NewHandle( sizeof( GFTInfo )) ; (**returnHandle).myID = GFTID ; /* to identify this as ours */ (**returnHandle).TEH = GetFieldTextHandle() ; if( !gError ) { LongToStr( gParamPtr, (long)returnHandle, handleStr ) ; gParamPtr->returnValue = PasToZero( gParamPtr, handleStr ) ; }} /* Get styled TEHandle for field specified in parameter 1 */TEHandle GetFieldTextHandle(){ Boolean cardFieldFlag = false ; int fieldID ; TEHandle fldTEHandle = NIL ; if( gParamPtr->paramCount < 1 || !**(gParamPtr->params[0]) ) SetError( "Missing field descriptor." ) ; else { HLock( gParamPtr->params[0] ) ; GetFieldInfo( *(gParamPtr->params[0]), &cardFieldFlag, &fieldID ) ; if( !gError ) fldTEHandle = GetFieldTE( gParamPtr, cardFieldFlag, fieldID, 0, NIL ) ; /* { TEStyleHandle styleH ; int nRuns, i ; styleH = GetStylHandle( fldTEHandle ) ; nRuns = (**styleH).nRuns ; for( i = 1 ; i <= nRuns ; i++ ) SysBeep(0); } */ HUnlock( gParamPtr->params[0] ) ; } return fldTEHandle ;}/* Returns field ID and card field boolean for field specified in fldDescriptor */GetFieldInfo( fldDescriptor, cardFieldFlag, fieldID )char * fldDescriptor ;Boolean *cardFieldFlag ;int *fieldID ;{ Str255 cString, pString ; Handle IDStrHandle ; Boolean error ; GetHCWord( fldDescriptor, 1, (char*)cString, &error ) ; if( !error ) { ZeroToPas( gParamPtr, (Ptr) cString, pString ) ; *cardFieldFlag = StringEqual( gParamPtr, pString, (StringPtr) "\pCD" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pCARD" ) ; if( *cardFieldFlag || StringEqual( gParamPtr, pString, (StringPtr) "\pBG" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pBKGND" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pBACKGROUND" )) { GetHCWord( fldDescriptor, 2, (char*)cString, &error ) ; if( !error ) ZeroToPas( gParamPtr, (Ptr) cString, pString ) ; } } /* Make sure first (or second) word is FLD or FIELD */ if( error || !(StringEqual( gParamPtr, pString, (StringPtr) "\pFLD" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pFIELD" ))) SetError( "Invalid field descriptor." ) ; else { strcpy((char*) cString, "the short id of " ) ; strcat((char*) cString, fldDescriptor ) ; ZeroToPas( gParamPtr, (Ptr) cString, pString ) ; IDStrHandle = EvalExpr( gParamPtr, pString ) ; if( gParamPtr->result != 0 ) /* EvalExpr failed => no such field */ SetError( "No such field." ) ; else { ZeroToPas( gParamPtr, *IDStrHandle, pString ) ; *fieldID = (int) StrToLong( gParamPtr, pString ) ; } }}SetError( errMsg )char *errMsg ;{ gError = true ; gParamPtr->returnValue = NewHandle( (long) (6 + strlen( errMsg )) + 1 ) ; strcpy( (char*)*(gParamPtr->returnValue), "Error " ) ; strcat( (char*)*(gParamPtr->returnValue), errMsg ) ;}/* Get the wordNumth word from a string (words delimited by spaces) and return it in a C string, truncated, if necessary, to 255 characters. */ void GetHCWord( char *inStr, int wordNum, char *outStr, Boolean *error ) { int len, curWord ; char *c, *d ; *error = false ; /* find start of our word by scanning through string, counting words */ if( *inStr == ' ' ) curWord = 0 ; else curWord = 1 ; for( c = inStr ; *c && (curWord < wordNum) ; c++ ) if( *c == ' ' && *(c+1) != ' ' ) curWord++ ; if( !*c ) /* we're at the end of the string already... */ *error = true ; /* ...so the word we wanted isn't there */ else { for( len = 0, d = outStr ; *c && (*c != ' ') && (len < 255) ; c++, d++, len++ ) *d = *c ; *d = '\0' ; if( *c != '\0' && *c != ' ' ) /* didn't hit the end of the word... */ *error = true ; /* ... so item too long for our allocated string */ }}</text>
</content>
<content>
<layer>card</layer>
<id>8</id>
<text>/* GetFieldText 1.0 © 1992 Trustees of Dartmouth College written in THINK C™ ©1991 Symantec Corporation by Susan Tenney, Dartmouth College Computing Services May, 199111/13/92 Roger Brown edited for THINK C 5.0.Returns styled text handle for a HyperCard field. Used in conjunction with SetFieldText to copy one field to another, keeping style information intact. Syntax: GetFieldText( fldDescriptor ) Returns: Handle to a copy of the styled text of the specified field. If there was an error, returns a message, the first word of which is "Error". Example: put GetFieldText( "fld someText" ) into thisText SetFieldText "fld someOtherText", thisText DisposeText( thisText ) Note that quotes are required around the field descriptor. Note also that once the text is no longer needed, its memory should be released with theDisposeText XCMD. To build the XFCN, create a Think C project with this, ANSI-A4,HyperXLib (callback library built for Think C), and MacTraps. Buildas code resource type XFCN with name GetFieldText.*/#include "HyperXCMD.h"#include "string.h"#include <SetUpA4.h>#define NIL 0L#define GFTID 40491L /* arbitrary ID */typedef struct { TEHandle TEH ; long myID ;} GFTInfo, **GFTHandle ;TEHandle GetFieldTextHandle() ;/* Global Variables */XCmdPtr gParamPtr ;Boolean gError ;/* procedures */void GetHCWord( char *inStr, int wordNum, char *outStr, Boolean *error ); pascal void main( paramPtr )XCmdPtr paramPtr ;{ RememberA0(); SetUpA4(); gParamPtr = paramPtr ; DoMyStuff() ; RestoreA4();}DoMyStuff(){ GFTHandle returnHandle ; TEHandle TEH ; Str255 handleStr ; gError = false ; returnHandle = (GFTHandle) NewHandle( sizeof( GFTInfo )) ; (**returnHandle).myID = GFTID ; /* to identify this as ours */ (**returnHandle).TEH = GetFieldTextHandle() ; if( !gError ) { LongToStr( gParamPtr, (long)returnHandle, handleStr ) ; gParamPtr->returnValue = PasToZero( gParamPtr, handleStr ) ; }} /* Get styled TEHandle for field specified in parameter 1 */TEHandle GetFieldTextHandle(){ Boolean cardFieldFlag = false ; int fieldID ; TEHandle fldTEHandle = NIL ; if( gParamPtr->paramCount < 1 || !**(gParamPtr->params[0]) ) SetError( "Missing field descriptor." ) ; else { HLock( gParamPtr->params[0] ) ; GetFieldInfo( *(gParamPtr->params[0]), &cardFieldFlag, &fieldID ) ; if( !gError ) fldTEHandle = GetFieldTE( gParamPtr, cardFieldFlag, fieldID, 0, NIL ) ; /* { TEStyleHandle styleH ; int nRuns, i ; styleH = GetStylHandle( fldTEHandle ) ; nRuns = (**styleH).nRuns ; for( i = 1 ; i <= nRuns ; i++ ) SysBeep(0); } */ HUnlock( gParamPtr->params[0] ) ; } return fldTEHandle ;}/* Returns field ID and card field boolean for field specified in fldDescriptor */GetFieldInfo( fldDescriptor, cardFieldFlag, fieldID )char * fldDescriptor ;Boolean *cardFieldFlag ;int *fieldID ;{ Str255 cString, pString ; Handle IDStrHandle ; Boolean error ; GetHCWord( fldDescriptor, 1, (char*)cString, &error ) ; if( !error ) { ZeroToPas( gParamPtr, (Ptr) cString, pString ) ; *cardFieldFlag = StringEqual( gParamPtr, pString, (StringPtr) "\pCD" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pCARD" ) ; if( *cardFieldFlag || StringEqual( gParamPtr, pString, (StringPtr) "\pBG" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pBKGND" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pBACKGROUND" )) { GetHCWord( fldDescriptor, 2, (char*)cString, &error ) ; if( !error ) ZeroToPas( gParamPtr, (Ptr) cString, pString ) ; } } /* Make sure first (or second) word is FLD or FIELD */ if( error || !(StringEqual( gParamPtr, pString, (StringPtr) "\pFLD" ) || StringEqual( gParamPtr, pString, (StringPtr) "\pFIELD" ))) SetError( "Invalid field descriptor." ) ; else { strcpy((char*) cString, "the short id of " ) ; strcat((char*) cString, fldDescriptor ) ; ZeroToPas( gParamPtr, (Ptr) cString, pString ) ; IDStrHandle = EvalExpr( gParamPtr, pString ) ; if( gParamPtr->result != 0 ) /* EvalExpr failed => no such field */ SetError( "No such field." ) ; else { ZeroToPas( gParamPtr, *IDStrHandle, pString ) ; *fieldID = (int) StrToLong( gParamPtr, pString ) ; } }}SetError( errMsg )char *errMsg ;{ gError = true ; gParamPtr->returnValue = NewHandle( (long) (6 + strlen( errMsg )) + 1 ) ; strcpy( (char*)*(gParamPtr->returnValue), "Error " ) ; strcat( (char*)*(gParamPtr->returnValue), errMsg ) ;}/* Get the wordNumth word from a string (words delimited by spaces) and return it in a C string, truncated, if necessary, to 255 characters. */ void GetHCWord( char *inStr, int wordNum, char *outStr, Boolean *error ) { int len, curWord ; char *c, *d ; *error = false ; /* find start of our word by scanning through string, counting words */ if( *inStr == ' ' ) curWord = 0 ; else curWord = 1 ; for( c = inStr ; *c && (curWord < wordNum) ; c++ ) if( *c == ' ' && *(c+1) != ' ' ) curWord++ ; if( !*c ) /* we're at the end of the string already... */ *error = true ; /* ...so the word we wanted isn't there */ else { for( len = 0, d = outStr ; *c && (*c != ' ') && (len < 255) ; c++, d++, len++ ) *d = *c ; *d = '\0' ; if( *c != '\0' && *c != ' ' ) /* didn't hit the end of the word... */ *error = true ; /* ... so item too long for our allocated string */ }}</text>
</content>
<content>
<layer>background</layer>
<id>44</id>
<text>HC2</text>
</content>
<content>
<layer>background</layer>
<id>45</id>
<text>New!</text>
</content>
<name>GetFieldText</name>
<script>on opencardput "Type some styled text here!" into cd fld "sourceText"set the textStyle of word 2 of cd fld "sourceText" to italicset the textStyle of word 3 of cd fld "sourceText" to underlineset the textStyle of word 5 of cd fld "sourceText" to shadowset the textSize of word 5 of cd fld "sourceText" to 18put empty into cd fld "destText"pass openCardend opencard</script>
</card>
card_22042.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<script>on mouseUpput "ListWindow" into wNameput "50,50,195,197" into wRectput 80 into colWidthput 12 into rowHeightput "monaco" into wFontput "9" into wSizeput "true" into wFloatsput true into multiSelput true into synchRowput true into typeSelput "Boise;ID" into dataput "Chico;CA" into line 2 of dataput "Denver;CO" into line 3 of dataput "Eugene;OR" into line 4 of dataput "Dover;DE" into line 4 of dataput "Gardner;MT" into line 5 of dataput "Houston;TX" into line 6 of dataput "Jefferson;MO" into line 7 of dataput "Laramie;WY" into line 8 of dataput "Norfolk;VA" into line 9 of dataput "Pittsburgh;PA" into line 10 of dataput "Quincy;MA" into line 11 of dataput "Syracuse;NY" into line 12 of dataput "Williston;RI" into line 13 of dataListWindow open,wName,wRect,colWidth,rowHeight,wFont,wSize,wFloats,multiSel,synchRow,typeSel,data,falseglobal gListWindowput the result into gListWindowif error is in gListWindow thenput gListWindowelseshow window id gListWindowend ifend mouseUp</script>
</part>
<part>
<id>5</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <false /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>286</left>
<top>170</top>
<right>495</right>
<bottom>294</bottom>
</rect>
<style>scrolling</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Geneva</font>
<textSize>9</textSize>
<textStyle>plain</textStyle>
<textHeight>12</textHeight>
<name>save</name>
<script>on mouseUphide meend mouseUp</script>
</part>
<part>
<id>9</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>262</left>
<top>311</top>
<right>431</right>
<bottom>333</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Show C Source</name>
<script>on mouseUplock screenif the short name of me is "Show C Source" thenset the visible of field "source" to trueset the visible of field "more source" to falseset the name of me to "Show C Source: part 2"else if the short name of me is "Show C Source: part 2" thenset the visible of field "more source" to trueset the visible of field "source" to falseset the name of me to "Hide C Source"elseset the visible of field "source" to falseset the visible of field "more source" to falseset the name of me to "Show C Source"end ifunlock screenend mouseUp</script>
</part>
<part>
<id>10</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>18</left>
<top>40</top>
<right>494</right>
<bottom>294</bottom>
</rect>
<style>scrolling</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <true /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Courier</font>
<textSize>10</textSize>
<textStyle>plain</textStyle>
<textHeight>13</textHeight>
<name>prototypes</name>
<script></script>
</part>
<content>
<layer>background</layer>
<id>44</id>
<text>HC2</text>
</content>
<content>
<layer>card</layer>
<id>5</id>
<text>This is an editable window. Try some typing, etc. test</text>
</content>
<content>
<layer>background</layer>
<id>45</id>
<text>New!</text>
</content>
<content>
<layer>background</layer>
<id>16</id>
<text><span class="style1">istWindow XCMD 1.0d3</span><span class="style2">Roger Brown</span><span class="style1"></span><span class="style2"> </span><span class="style1">ListWindow</span><span class="style2"> is an external window XCMD that presents a ListManager type of table. Data cannot be edited in the window. Selections can be one-at-a time or multiple. All cells have the same size. All cells have the same font and font size. There are no dividing lines between cells. The XCMD understands these direct calls: ListWindow version - returns the version number of the XCMD. ListWindow open, name, rect, columnWidth, rowHeight, font, fontSize, floating, multipleSelection, synchRow, typeSelect,data where "open" is the command to open a new window. "name" is the window title. "rect" is the window rect in global screen coordinates. "columnWidth" is the pixel width of each cell "rowHeight" is the pixel height of each cell. "font" is the name of the font to use "fontSize" is the size of the font to use "floating" is true or false: is it a floating window? "multipleSelection" is true or false: can the user choose more than one cell? "synchRow" is true or false. If it is true, selecting any one cell will result in the automatic selection of all cells in the same row. "typeSelect" is true or false. This parameter controls the "select by typing" action described below. "data" is a contianer that holds the data to be presented. It must be formatted as one line per table row, each line with column data delimited using semi-colons. We use semi-colons instead of commas so that cell data can contain commas. Ex. Augusta;ME<CR> Burlington;VT<CR> Chico;CA<CR> "zoom" is true if you want a zoom box in the window. Note: the zoom always zooms to the same screen as the card window. None of these parameters except "open" are required. There are default values for all of them: name: ListWindow rect: 20,50,116,250 colWIdth: 100 rowHeight: 15 font: monaco fontSize: 9 floating: false multipleSelection: false synchRow: false typeSelect: false data: empty ListWindow "open" returns the ID of the new window or error messages. The number of rows is initially set equal to the number of lines in the input data. The number of columns is set equal to the number of semi-colon delimited items in the first line. You can add and delete rows using the following "send" message syntax: send "insert row n data1;data2;data3;.. dataN" to window ListWindow where n is the number of the row to insert after and data1;data2, etc are the data fields for the row send "delete row n" to window ListWindow where n is the number of the row to delete; Windows are created invisible so that you can adjust the data before showing them. To open and show a window, use this syntax: ListWindow Open,... other parameters.. put the result into windowID -- adjust data here show window id windowID You can create any number of windows with ListWindow. They can all have the same name if you like. Each will have a unique id, however. Each window can have different properties. A vertical scroll bar is always created in the window. A horizontal scroll bar is created if there is more than one column. There is a limit of 32K of data. You can set these properties: - visible - rect - loc You can get these properties: - visible - rect - loc If "typeSelect" is true, the user can select cells by typing in a manner similar to the standard SFGetFile box. It is not exactly the same. Only cells that start with the typed text will be selected. When there are more than one column in the list, type selection will scan across columns before going down to the next row. The resulting behavior can be confusing. This feature makes more sense when there is a single column and multiple selection is off. It also works best when the list is sorted alphabetically. The user commits a selection in one of two ways: if multiple selection is off, a single click commits the selection. If multiple selection is on, a double click on any cell commits the current selection. When either of these events occurs, ListWindow sends the message "MouseDownInListWindow windowID" to the current card. The windowID property identifies which window the action occurred in, in case you have more than one list window open. At that time, you can get a list of the currentlu selected cells from the global variable XXLWSelection. The selection are presented one cell to a line, each line consisting of the row number, the column number, and the text as items. REVISION HISTORY 1.0d1 1/30/93 First public release. 1.0d2 3/16/93 Add zoom parameter. 1.0d3 3/31/93 Dispose a dangling handle.</span></text>
</content>
<content>
<layer>background</layer>
<id>37</id>
<text><span class="style5">* Do an update event. */void DoUpdate(void){ GrafPtr gp; /* We already set the port. */ BeginUpdate(gWindow); EraseRect(&gWindow->portRect); DrawWindow(); EndUpdate(gWindow);}/* Show I-beam cursor if appropriate. */void CheckCursor(void){ Point mp; Rect r; InitCursor();}/* Handle an open event. */void DoOpenEvent(void){ XWAllowReEntrancy(gParamPtr,gWindow,TRUE,TRUE); /* and allow reentrancy for update events */ if ((**gH).floats) { /* If we float, grab edit control and set ibeam */ ActivateEdit(TRUE); } }/* Handle a close event */void DoCloseEvent(void){ int r,c; char s1[256]; Handle h; Boolean okToClose = TRUE; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; if (gWindow == NULL) return; /* This can happen, really. */ gParamPtr->passFlag = TRUE; /* Clean up memory allocations. */ ActivateEdit(FALSE); if ((**gH).theList != NULL) LDispose((**gH).theList); DisposHandle(gH); gWindow = NULL;}/* Handle a key event */void DoKeyEvent(EventRecord *theEvent){ /* check command keys */ if ((theEvent->modifiers & cmdKey) != 0) return; TypeSelect(theEvent);}/* return the upper case equivalent of a lower case character */char uchar(char c){ c = (c>='a')&&(c<='z') ? (c-('a'-'A')) : c; return c;}/* string selection logic for selection via typed characters */pascal int MySelect(Ptr aPtr,Ptr bPtr,int aLen,int bLen){ /* return 0 if string a >= string b, else return 1 */ char a[256],b[256]; int i,compare; /* restrict comparison to 255 bytes max */ aLen = min(aLen,255); bLen = min(bLen,255); for (i=0;i<aLen;i++) a[i] = uchar(*(aPtr+i)); a[aLen] = 0; for (i=0;i<bLen;i++) b[i] = uchar(*(bPtr+i)); b[bLen] = 0; if (StrStartsWith(a,b)) return 0; return 1;}void MyLSetSelect(Boolean setIt,Cell theCell){ int i; if ((**gH).synchRow) { for (i=0;i<(**gH).numCol;i++) { theCell.h = i; LSetSelect(setIt,theCell,(**gH).theList); } } else LSetSelect(setIt,theCell,(**gH).theList);}/* scroll selection list up or down */void ScrollList(char c){ Cell oldCell,aCell; Boolean noneSelected; SetPt(&oldCell,0,0); SetPt(&aCell,0,0); if (LGetSelect(TRUE,&oldCell,(**gH).theList)) { /* get current selection */ if (c==upArrow) { SetPt(&aCell,oldCell.h,max(0,oldCell.v-1)); } else if (c==downArrow) { SetPt(&aCell,oldCell.h,min((**(**gH).theList).dataBounds.bottom-1,oldCell.v+1)); } else if (c==rightArrow) { SetPt(&aCell,min((**(**gH).theList).dataBounds.right-1,oldCell.h+1),oldCell.v); } else if (c==leftArrow) { SetPt(&aCell,max(0,oldCell.h-1),oldCell.v); } if (EqualPt(oldCell,aCell)==1) { return; } } MyLSetSelect(FALSE,oldCell); /* clear current selection */ MyLSetSelect(TRUE,aCell); /* set the new one */ LAutoScroll((**gH).theList);}/* Select by typing - Simulates SFGetFile dialog action except that the typed text must actually be in the cell. */void TypeSelect(EventRecord *theEvent){ int c; long dummy; int iType; Handle iHandle; Rect iBox; char result,theChar; Cell aCell,oldCell; Boolean found, somethingSelected; char x1[256],x2[256]; theChar = BitAnd(theEvent->message,charCodeMask); if (TickCount() > (**gH).charTime) { if ((**gH).multiSel) { SetPt(&aCell,-1,-1); (**gH).lastTypedCell = aCell; } (**gH).charPos = 0; } (**gH).collector[(**gH).charPos] = theChar; if (((**gH).collector[(**gH).charPos] ==13)|| ((**gH).collector[(**gH).charPos]==3)) { /* is CR, use as normal */ ScrollList(downArrow); (**gH).charPos = 0; return; } else if ((theChar < downArrow+1) && theChar > (leftArrow-1)) { /* move cursor */ ScrollList(theChar); (**gH).charPos = 0; return; } else { (**gH).charPos++; (**gH).collector[(**gH).charPos] = 0; (**gH).charTime = TickCount()+45L; } if (!(**gH).typeSelect) return; SetPt(&oldCell,0,0); /* get current selection */ somethingSelected = LGetSelect(TRUE,&oldCell,(**gH).theList); SetPt(&aCell,0,0); found = LSearch((**gH).collector,strlen((**gH).collector),MySelect,&aCell,(**gH).theList); if (found==TRUE) { if ((somethingSelected==FALSE) || (!EqualPt(oldCell,aCell))) { if ((**gH).multiSel) oldCell = (**gH).lastTypedCell; MyLSetSelect(FALSE,oldCell); /* clear current selection */ MyLSetSelect(TRUE,aCell); /* set the new one */ if ((**gH).multiSel) (**gH).lastTypedCell = aCell; LAutoScroll((**gH).theList); } } }/* return true if something is selected */Boolean SomethingSelected(void ){ Point aCell; SetPt(&aCell,0,0); return (LGetSelect(TRUE,&aCell,(**gH).theList)); }/* Handle an activate event. */void DoActivateEvent(EventRecord *theEvent){ OSErr err; if (theEvent->modifiers & activeFlag ) { /* activate */ ActivateEdit(TRUE); } else { err = ZeroScrap(); /* export the scrap */ ActivateEdit(FALSE); /* turn off edit */ }}/* Handle the app4 event if and only if its a suspend/resume event *//* The only action we take is to convert the scrap to and from the public scrap */void HandleApp4Evt(EventRecord *theEvent){ OSErr err; if (App4Selector(theEvent) == SUSPEND_RESUME_SELECTOR) { if SuspResIsSuspend(theEvent->message) { if (ScrapDataHasChanged(theEvent->message)) { } if ((**gH).floats) HideWindow(gWindow); /* if floats, hide it */ ActivateEdit(FALSE); } else { ShowWindow(gWindow); /* show window */ if ((**gH).haveEdit) ActivateEdit(TRUE); /* hilite the selection */ } }} /* Handle mouse events in window content region */void DoInContent(EventRecord *theEvent,WindowPtr theWindow){ int partCode; /* control part */ ControlHandle theControl; /* the control hit */ Cell aCell; Boolean doubleClick; GlobalToLocal(&theEvent->where); if (!PtInRect(theEvent->where,&gWindow->portRect)) return; partCode = FindControl(theEvent->where,theWindow,&theControl); /* Let ListManager handle the click first */ doubleClick = LClick(theEvent->where, theEvent->modifiers, (**gH).theList); if (partCode != 0) /* in scroll bar, do nothing else */ return; if ((**gH).synchRow) { /* select the whole row */ SynchAllRows(); } /* send selection message */ if ((doubleClick || !(**gH).multiSel) && (theEvent->modifiers == 0)) DoSelClick(); }void SynchAllRows(void){ int i,j; Cell lastCell,aCell; lastCell = LLastClick((**gH).theList); for (i=0;i<(**gH).numRows;i++) { lastCell.v = i; for (j=0;j<(**gH).numCol;j++) { aCell.h = j;aCell.v = i; MyLSetSelect(LGetSelect(FALSE,&lastCell,(**gH).theList),aCell); } }}/* extract the user selections */void GetListSelections(Handle aHandle){ char someSelect; Cell aCell; int stringLength,t,b,i,j; Str255 s1,s2,theText; long n,len; SetHandleSize(aHandle,1L); /* start with a null string */ HLock(aHandle); strcpy(*aHandle,""); for (j=0;j<(**gH).numRows;j++) { for (i=0;i<(**gH).numCol;i++) { SetPt(&aCell, i, j); someSelect = LGetSelect(FALSE, &aCell, (**gH).theList); if (someSelect==TRUE) { stringLength = 240; LGetCell(theText, &stringLength, aCell, (**gH).theList); n = aCell.v+1; theText[stringLength] = 0; NumToString(n,s1); PtoCstr((char *)s1); strcat((char*)s1,","); n = aCell.h+1; theText[stringLength] = 0; NumToString(n,s2); PtoCstr((char *)s2); strcat((char*)s1,(char *)s2); strcat((char*)s1,","); strcat((char*)s1,(char*)theText); strcat((char*)s1,"\15"); /* divide into lines */ len = GetHandleSize(aHandle); len = len + strlen((char*)s1); HUnlock(aHandle); SetHandleSize(aHandle,len); if (MemError() != noErr) { strcpy(*aHandle,"Out of memory"); return; } HLock(aHandle); strcat(*aHandle,(char*)s1); aCell.h++; } } } len = GetHandleSize(aHandle); if (len>1L) { *(*aHandle+len-2L) = 0; /* trim off the last return */ }}void DoSelClick(void){ Handle h; char s1[256],s2[256]; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; strcpy(s1,"MouseDownInListWindow "); NumToString((long)gWindow,s2); PtoCstr(s2); strcat(s1,s2); CtoPstr(s1); h = NewHandle(0L); GetListSelections(h); SetGlobal(gParamPtr,"\pXXLWSelection",h); DisposHandle(h); savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; SendCardMessage(gParamPtr,(StringPtr)s1); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH;}/* =============== Window Management ================ *//* Draw the window. */void DrawWindow(void){ Rect r; Str255 title; SetPort(gWindow); r = gWindow->portRect; ClipRect(&r); DrawList(); DrawGrowIcon(gWindow);}void DrawList(void)/* draw the selection list */{ RgnHandle theRgn; Rect listFrame; ClipRect(&gWindow->portRect); theRgn = NewRgn(); RectRgn(theRgn, &gWindow->portRect); LUpdate(theRgn, (**gH).theList); DisposeRgn(theRgn);}/* Resize the window. */void MyGrowWindow(WindowPtr window,long result){ int newWidth,newHeight; Rect r; SetPort(gWindow); r = gWindow->portRect; EraseRect(&r); newWidth = (int)LoWord(result); newHeight = HiWord(result); SizeWindow(window,newWidth,newHeight,TRUE); r = gWindow->portRect; LSize(r.right - kSBarSize + 1,r.bottom - kSBarSize + 1,(**gH).theList); InvalRect(&r); BeginUpdate(gWindow); DrawWindow(); EndUpdate(gWindow);}/* Turn editing on or off. */void ActivateEdit(Boolean activate){ OSErr err; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; if (gWindow==NULL) return; SetPort(gWindow); ClipRect(&gWindow->portRect); if (activate) { savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; BeginXWEdit(gParamPtr,gWindow); /* get edit control */ gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; (**gH).haveEdit = TRUE; } else { savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; EndXWEdit(gParamPtr,gWindow); /* give up edit control */ gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; (**gH).haveEdit = FALSE; /* export the scrap in case some other editable window wants it */ err = ZeroScrap(); if (err==noErr) ; } }/* =================== Window Properties and Messages =================== *//* Format a proerty value expressed as a string. */Handle FormatProperty(char *s){ long len; Handle h; len = 1+strlen(s); h = NewHandle(len); BlockMove(s,*h,len); return h;}/* get the requested property. */void GetProperty(void){ char *message; XWEventInfoPtr theInfo; char numStr[256],prop[256]; int error; Rect r1,r2; Point p; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; theInfo = (XWEventInfoPtr)gParamPtr->params[0]; message = (char*)(Handle)(theInfo->eventParams[0]); PtoCstr(message); strcpy(prop,message); CtoPstr(prop); UprString(prop,TRUE); gParamPtr->passFlag = FALSE; if (EqualString(prop,"\pVISIBLE",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(prop,"\pLOC",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(prop,"\pRECT",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; }}/* Set the requested property. */void SetProperty(void){ char *message; XWEventInfoPtr theInfo; Rect r1,r2; char s[256],num[256]; long start,end,n; int i; long growResult; Point p; long len,teLen; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; FontInfo fi; theInfo = (XWEventInfoPtr)gParamPtr->params[0]; message = (char*)(Handle)(theInfo->eventParams[0]); PtoCstr(message); strcpy(s,message); CtoPstr(s); UprString(s,TRUE); gParamPtr->passFlag = FALSE; if (EqualString(s,"\pVISIBLE",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(s,"\pLOC",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(s,"\pRECT",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } }/* Handle a "send" message. */void DoSendEvent(void){ char *message; XWEventInfoPtr theInfo; long n1,n2; char save[256],s[256]; /* Get the message text. Its a P String. */ theInfo = (XWEventInfoPtr)gParamPtr->params[0]; message = (char*)(Handle)(theInfo->eventParams[0]); PtoCstr(message); strcpy(save,message); ucase(message); /* Messages: INSERT ROW n insert after row n DELETE ROW n delete row n */ if (StrContains(message,"INSERT")) { pickoff(save,' ',s); /* strip first word */ pickoff(save,' ',s); /* strip second word */ pickoff(save,' ',s); /* get second word */ if (IsNumber(s,&n1)) { /* row number */ InsertRow(n1,save); return; } } if (StrContains(message,"DELETE")) { pickoff(save,' ',s); /* strip first word */ pickoff(save,' ',s); /* strip second word */ pickoff(save,' ',s); /* get second word */ if (IsNumber(s,&n1)) { /* row number */ DeleteRow(n1); return; } } strcpy(s,"ListWindow cannot understand: "); strcat(s,message); ResultIs(gParamPtr,s);}void InsertRow(long row, char *data) { char s[256]; Cell aCell; int i; LAddRow(1,row,(**gH).theList); for (i=0;i<(**gH).numCol;i++) { GetDelimitedItem(';',data,i+1,s); SetPt(&aCell,i,row); LSetCell(s, (int)strlen(s), aCell, (**gH).theList); }}/* delete a row */void DeleteRow(long row) { LDelRow(1,(int)row-1,(**gH).theList);}/* ================== Window Static Global Data ============= *//* Handle load and store of static global block that hangs off the XWindow refcon. After a create of load, we lock the handle so that the rest of the XCMD can directly use the fields of the record stored at the handle. *//* Create a heap block to store our static globals in. */void CreateStaticGlobals(void){ long len; /* create the handle */ len = sizeof(StaticGlobals); gH = NULL; gH = (StaticGlobalsH)NewHandle(len); if (gH != NULL) HLock((Handle)gH);}/* Load the static globals and lock them down for our use. */ void LoadStaticGlobals(void){ if (gWindow==NULL) return; /* follows a close operation */ gH = (StaticGlobalsH)((WindowPeek)gWindow)->refCon; if (gH==NULL) { DebugStr("\pnull globals handle"); /* need better report */ return; } HLock((Handle)gH); }/* Return true if target string starts with test string. Match is not case sensitive. */Boolean StrStartsWith(char *target,char *test) { char *j,*k; int targetLen,testLen; Str255 s; targetLen = strlen(target); /* scan this far, max */ testLen = strlen(test); /* look for this many matches */ j = target; k = test; while (uchar(*j)==uchar(*k)) { /* loop while they match */ j++; k++; if (k==(test+testLen)) return TRUE; /* got it */ } return FALSE; /* no match */}/* Get HyperCard comma delimited item i from item list string inStr. Return it in outStr *//* item must be smaller than 255 characters */void GetDelimitedItem(char delim,char *inStr,int i,char *outStr){ int c; /* character pointer */ int len; /* length to scan */ int count; /* count of items found */ int j; /* item byte count */ char temp[256]; /* collect item here, hope its < 255 */ count = j = 0; /* initialize */ len = strlen(inStr); /* go this far, max */ for (c=0;c<len;c++) { if (inStr[c]==delim) { /* at an item boundary */ count = count + 1; /* bump counter */ if (count==i) break; /* if this is it, stop scanning */ j = 0; /* else start on the next item */ } else { temp[j] = inStr[c]; /* collect characters to return */ j++; /* go to next */ if (j==255) { /* sorry, too big to store */ strcpy(temp,"Error: Item > 255 characters."); return; } if (c==(len-1)) { /* last item, no comma */ count = count+1; break; } } } if (count < i) outStr[0] = 0; /* no item there */ else { temp[j] = 0; /* make it a C string */ strcpy(outStr,temp); /* move to output string */ } return;}</span></text>
<text>/* ListWindow *//* External Window example *//* Roger Brown Software Development, Kiewit Computation Center, Dartmouth College © 1992 Trustees of Dartmouth College Written in THINK C © 1991 Symantec Corp. ListWindow is an external window XCMD that presents a ListManager type of table. Data cannot be edited in the window. Selections can be one-at-a time or multiple. All cells have the same size. All cells have the same font and font size. There are no dividing lines between cells. The XCMD understands these direct calls: ListWindow version - returns the version number of the XCMD. ListWindow open, name, rect, columnWidth, rowHeight, font, fontSize, floating, multipleSelection, synchRow, typeSelect, data, zoom where "open" is the command to open a new window. "name" is the window title. "rect" is the window rect in global screen coordinates. "columnWidth" is the pixel width of each cell "rowHeight" is the pixel height of each cell. "font" is the name of the font to use "fontSize" is the size of the font to use "floating" is true or false: is it a floating window? "multipleSelection" is true or false: can the user choose more than one cell? "synchRow" is true or false. If it is true, selecting any one cell will result in the automatic selection of all cells in the same row. "typeSelect" is true or false. This parameter controls the "select by typing" action described below. "data" is a container that holds the data to be presented. It must be formatted as one line per table row, each line with column data delimited using semi-colons. We use semi-colons instead of commas so that cell data can contain commas. Ex. Augusta;ME<CR> Burlington;VT<CR> Chico;CA<CR> "zoom" is true if you want a zoom box in the window. None of these parameters except "open" are required. There are default values for all of them: name: ListWindow rect: 20,50,116,250 colWIdth: 100 rowHeight: 15 font: monaco fontSize: 9 floating: false multipleSelection: false synchRow: false typeSelect: false data: empty ListWindow "open" returns the ID of the new window or error messages. The number of rows is initially set equal to the number of lines in the input data. The number of columns is set equal to the number of semi-colon delimited items in the first line. You can add and delete rows using the following "send" message syntax: send "insert row n data1;data2;data3;.. dataN" to window ListWindow where n is the number of the row to insert after and data1;data2, etc are the data fields for the row send "delete row n" to window ListWindow where n is the number of the row to delete; Windows are created invisible so that you can adjust the data before showing them. To open and show a window, use this syntax: ListWindow Open,... other parameters.. put the result into windowID -- adjust data here show window id windowID You can create any number of windows with ListWindow. They can all have the same name if you like. Each will have a unique id, however. Each window can have different properties. A vertical scroll bar is always created in the window. A horizontal scroll bar is created if there is more than one column. There is a limit of 32K of data. You can set these properties: - visible - rect - loc You can get these properties: - visible - rect - loc If "typeSelect" is true, the user can select cells by typing in a manner similar to the standard SFGetFile box. It is not exactly the same. Only cells that start with the typed text will be selected. When there are more than one column in the list, type selection will scan across columns before going down to the next row. The resulting behavior can be confusing. This feature makes more sense when there is a single column and multiple selection is off. It also works best when the list is sorted alphabetically. The user commits a selection in one of two ways: if multiple selection is off, a single click commits the selection. If multiple selection is on, a double click on any cell commits the current selection. When either of these events occurs, ListWindow sends the message "MouseDownInListWindow windowID" to the current card. The windowID property identifies which window the action occurred in, in case you have more than one list window open. At that time, you can get a list of the currentlu selected cells from the global variable XXLWSelection. The selection are presented one cell to a line, each line consisting of the row number, the column number, and the text as items. A note on reentrancy: This XCMD allows reentrancy so that we can support the creation of multiple windows and have updating work correctly. To do this safely, we make sure to protect our global data when we make certain callbacks to HyperCard. The reason for this is that some callbacks can result in events being generated for one of our windows. When that happens, the XCMD is reentered while it is already executing and the data global can change. To protect our globals, we save a copy of each on the stack (in local function variables) and restore them after the callback. Here is some sample code: savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; screenRectH = EvalExpr(gParamPtr,"\pthe screenRect"); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; To build the XCMD: Create a project with this source, OSChecks.c, ANSI-A4, HyperXLib, and MacTraps. Set project type to Code Resource, name ListWindow, ID -1143, type XCMD. You will need the HCUtilities library as well. It is an include file for this file. REVISION HISTORY 1.0d0 10/30/92 First public release. 1.0d3 3/31/93 Dispose screenRectH. 1.0d2 3/16/92 Add zoom parameter to put a zoom box in the window. *//* C library headers needed */#include "stdio.h"#include "ctype.h"#include "string.h"#include "math.h"#include "limits.h"#include "Windows.h"#include "HyperXCmd.h"#include "HCUtilities.c"#include <SetUpA4.h>/* prototypes */#include "ListWindow.h" /* constants */#define VERSION "ListWindow version 1.0d3, © Trustees of Dartmouth College, 1992" #define kSBarSize 16#define kLeftMargin 5#define kTopMargin 5#define downArrow 31 /* down arrow key */#define upArrow 30 /* up arrow key */#define rightArrow 29 /* right arrow key */#define leftArrow 28 /* left arrow key */#define kStdLDEF 0/* globals *//* This structure holds all of the data that we want to keep constant across calls of the XCMD for a certain window. */ typedef struct StaticGlobals{ int windowType; Rect windowRect; int font, textSize; Boolean floats; Rect growRect; Boolean haveEdit; ListHandle theList; int numRows,numCol; int colWidth,rowHeight; Boolean multiSel; long charTime; char collector[32]; int charPos; Cell lastTypedCell; Boolean synchRow; Boolean typeSelect;}StaticGlobals,*StaticGlobalsP,**StaticGlobalsH;WindowPtr gWindow; /* pointer to the window */XCmdPtr gParamPtr; /* the XCMD block pointer */StaticGlobalsH gH; /* our static global data *//* ======================== Main Entry Point ================ *//* The main entry point for the XCMD dispatches messages or events */pascal void main(paramPtr)XCmdPtr paramPtr ;{ /* we have globals, so manipulate A4 to remember them */ RememberA0(); SetUpA4(); /* remember paramptr globally */ gParamPtr = paramPtr; if(gParamPtr->paramCount == -1) { /* Do a regular Macintosh event */ DoMacEvent(); } else { /* or do an XCMD message call */ DoXCMDCall(); } RestoreA4(); } /* ======================= XCMD call processing =============== *//* Handle a call from a script (except for "send..."). These are the messages that we have defined as valid parameters for an XXCMD call. */void DoXCMDCall(void){ int i; Handle taskHandle; char temp[256]; for (i=0;i<gParamPtr->paramCount;i++) HLock(gParamPtr->params[i]); /* get the opcode */ taskHandle = gParamPtr->params[0]; ucase(*taskHandle); /* branch on the opcode */ if (strcmp(*taskHandle,"VERSION")==0) ReturnVersion(); else if (strcmp(*taskHandle,"OPEN")==0) DoOpenWindow(); else { strcpy((char*)temp,"XWindow Error: unknown message "); strcat((char*)temp,*taskHandle); ResultIs(gParamPtr,temp); }} /* return the version number */void ReturnVersion(void){ ResultIs(gParamPtr,VERSION);}/* Open a window. */void DoOpenWindow(void){ GrafPtr savePort; WindowPtr windPtr; char name[256]; int result; strcpy(name,"ListWindow"); /* default name */ if ((gParamPtr->paramCount > 2) && (strlen(*gParamPtr->params[1]) > 0)) strcpy((char*)name,*gParamPtr->params[1]); result = CreateWindow(name); switch(result) { case xresNotImp: ResultIs(gParamPtr,"Error: External windows not implemented" ) ; break; case xresFail: ResultIs(gParamPtr,"Error: Could not create external window" ) ; break; default : /* return the window pointer */ NumToString((long)gWindow,name); PtoCstr((char*)name); ResultIs(gParamPtr,name) ; break; }}/* Create a new window */int CreateWindow(char *name){ WindowPtr wind; Rect r; int windowType; Str255 s; CreateStaticGlobals(); if (gH == NULL) { return xresFail; } GetWindowParameters(); /* set other window parameters or defaults */ strcpy((char*)s,name); CtoPstr((char*)s); windowType = (**gH).windowType; /* Create the window invisble. Show it from a script. This lets us set properties before it is first shown. */ wind = NewXWindow(gParamPtr,&(**gH).windowRect,s,FALSE,windowType,FALSE,(**gH).floats); if( gParamPtr->result != xresSucc) { DisposHandle(gH); } else { gWindow = wind; XCMDInitWindow(); } return gParamPtr->result;} /* ===================== Mac event processing ====================== *//* process a Macintosh event */void DoMacEvent(void){ GrafPtr savePort ; EventRecord event ; /* what window is this for? */ gParamPtr->passFlag = FALSE ; gWindow = ((XWEventInfoPtr)(gParamPtr->params[0]))->eventWindow; /* load the window's globals */ LoadStaticGlobals(); /* get the event */ event = ((XWEventInfoPtr)(gParamPtr->params[0]))->event; GetPort(&savePort) ; SetPort(gWindow) ; /* do the event */ DispatchMacEvent(&event ) ; SetPort(savePort); } /* dispatch a Macintosh event */void DispatchMacEvent(EventRecord *evt ){ switch( evt->what ) { case mouseDown: DoMouseDown(evt); break; case updateEvt: DoUpdate(); break; case xCursorWithin: CheckCursor(); break; case xOpenEvt: DoOpenEvent(); break; case xCloseEvt: DoCloseEvent(); break ; case keyDown: case autoKey: DoKeyEvent(evt); break; case activateEvt: DoActivateEvent(evt); break; case app4Evt: HandleApp4Evt(evt); break; case xGiveUpEditEvt: ActivateEdit(FALSE); break; case xSetPropEvt: SetProperty(); break; case xGetPropEvt: GetProperty(); break; case xSendEvt: DoSendEvent(); break; case xHidePalettesEvt: HideWindow(gWindow); break; case xShowPalettesEvt: ShowWindow(gWindow); break; default : break; } } /* ================== Initialization ================ *//* Parse out the window parameters sent from HyperTalk, use defaults for those that are not defined. */void GetWindowParameters(void){ Str255 s; long n; int i; Rect r; /* window defaults */ #define cWRLeft 20 #define cWRTop 50 #define cWRRight 116 #define cWRBottom 250 #define cColWidth 100 #define cRowHeight 15 #define cFont monaco #define cTextSize 9 (**gH).windowType = documentProc; /* param[1] has the window name */ /* param[2] has the window rect */ /* param[3] has the column width */ /* param[4] has the row height */ /* param[5] has the font */ /* param[6] has the font size */ /* param[7] has the floating flag */ /* param[8] has the multi-selection boolean */ /* param[9] has the synchRow parameter */ /* param[10] has the type-selection flag */ /* param[11] has the data */ /* param[12] has the zoom flag */ /* check for a rectangle parameter */ if ((gParamPtr->paramCount > 2)&&(strlen(*gParamPtr->params[2]) > 0)) { CtoPstr(*gParamPtr->params[2]); StrToRect(gParamPtr,(StringPtr)*gParamPtr->params[2],&(**gH).windowRect); } else SetRect(&(**gH).windowRect,cWRLeft,cWRTop,cWRRight,cWRBottom); /* size is hard wired */ /* check for col width */ (**gH).colWidth = cColWidth; if (gParamPtr->paramCount > 3) { strcpy((char*)s,*gParamPtr->params[3]); if (strlen((char*)s) > 0) { if (IsNumber((char*)s,&n)) (**gH).colWidth = n; } } /* check for row height */ (**gH).rowHeight = cRowHeight; if (gParamPtr->paramCount > 4) { strcpy((char*)s,*gParamPtr->params[4]); if (strlen((char*)s) > 0) { if (IsNumber((char*)s,&n)) (**gH).rowHeight = n; } } /* check for a font name */ (**gH).font = cFont; if (gParamPtr->paramCount > 5) { strcpy((char*)s,*gParamPtr->params[5]); if (strlen((char*)s) > 0) { CtoPstr(s); GetFNum(s,&i); (**gH).font = i; } } /* check for font size */ (**gH).textSize = cTextSize; if (gParamPtr->paramCount > 6) { strcpy((char*)s,*gParamPtr->params[6]); if (strlen((char*)s) > 0) { if (IsNumber((char*)s,&n)) (**gH).textSize = n; } } /* check for "floats" flag */ (**gH).floats = false; if (gParamPtr->paramCount > 7) { ucase(*gParamPtr->params[7]); if (strcmp(*gParamPtr->params[7],"TRUE")==0) { (**gH).floats = TRUE; (**gH).windowType = paletteProc+hasTallTBar; } } /* check for multiple selection flag */ (**gH).multiSel = FALSE; if (gParamPtr->paramCount > 8) { strcpy((char*)s,*gParamPtr->params[8]); if (strlen((char*)s) > 0) { CtoPstr(s); if (EqualString(s,"\pTRUE",FALSE,FALSE)) (**gH).multiSel = TRUE; else if (EqualString(s,"\pFALSE",FALSE,FALSE)) (**gH).multiSel = FALSE; } } /* check for "synchRow" flag */ (**gH).synchRow = FALSE; if (gParamPtr->paramCount > 9) { ucase(*gParamPtr->params[9]); if (strcmp(*gParamPtr->params[9],"TRUE")==0) { (**gH).synchRow = true; } } /* check for "typeSelect" flag */ (**gH).typeSelect = FALSE; if (gParamPtr->paramCount > 10) { ucase(*gParamPtr->params[10]); if (strcmp(*gParamPtr->params[10],"TRUE")==0) { (**gH).typeSelect = true; } } /* check for "zoom" flag */ if (gParamPtr->paramCount > 12) { ucase(*gParamPtr->params[12]); if (strcmp(*gParamPtr->params[12],"TRUE")==0) { if ((**gH).windowType == documentProc) (**gH).windowType = zoomDocProc; else if ((**gH).windowType == paletteProc+hasTallTBar) (**gH).windowType = palZoomProc+hasTallTBar; } } (**gH).charPos = 0; (**gH).collector[0] = 0;}/* Initialize the window. */void XCMDInitWindow(void){ int width,height; /* rect dimensions */ Rect r; /* utility rect */ Rect vRect,dRect; /* TE rects */ Handle screenRectH; /* handle to the screen rect from HC */ XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; /* remember the globals handle */ ((WindowPeek)gWindow)->refCon = (long)gH; /* get grow limit */ /* See callback protection note at top of file */ savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; screenRectH = EvalExpr(gParamPtr,"\pthe screenRect"); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; CtoPstr(*screenRectH); StrToRect(gParamPtr,(StringPtr)*screenRectH,&r); (**gH).growRect = r; (**gH).growRect.right = r.right - r.left; (**gH).growRect.bottom = r.bottom - r.top; (**gH).growRect.left = (**gH).colWidth + kSBarSize; (**gH).growRect.top = 60; SetZoomRect(&r); DisposHandle(screenRectH); MakeList(); if (gParamPtr->paramCount > 11) LoadData(*gParamPtr->params[11]); }/* Set the window zoom rect. */void SetZoomRect(Rect *screenRect){ WStateData *ws; WindowPeek wp; Handle dh; Rect zoomRect; wp = (WindowPeek)gWindow; dh = wp->dataHandle; ws = (WStateData *)(*dh); zoomRect = *screenRect; InsetRect(&zoomRect,3,3); zoomRect.top += 40; ws->stdState = zoomRect;}void MakeList(void){ Rect dataBounds,r; Point cellSize; int gCellWidth; int gCellHeight = 12; char aString[256],*p; SetPort(gWindow); (**gH).theList = NULL; if (gParamPtr->paramCount > 11) { GetHCLine(*gParamPtr->params[11],1,aString); (**gH).numCol = 1; p = aString; while (*p != 0) { if (*p == ';') (**gH).numCol ++; p++; } (**gH).numRows = NumHCLines(*gParamPtr->params[11]); } else { (**gH).numCol = 1; (**gH).numRows = 1; } SetRect(&dataBounds, 0, 0, (**gH).numCol, (**gH).numRows); SetPt(&cellSize, (**gH).colWidth, (**gH).rowHeight); r = gWindow->portRect; r.right -= kSBarSize -1; r.bottom -= kSBarSize -1; TextFont((**gH).font); TextSize((**gH).textSize); TextFace(0); (**gH).theList = NULL; (**gH).theList = LNew(&r, &dataBounds, cellSize, kStdLDEF, gWindow, TRUE, TRUE, (**gH).numCol > 1, TRUE); MoveHHi((Handle)(**gH).theList); HLock((Handle)(**gH).theList); if ((**gH).multiSel) (**(**gH).theList).selFlags = lNoRect+lNoExtend+lUseSense; else (**(**gH).theList).selFlags = lOnlyOne;}void LoadData(char *theField){ int i,j,row,col,fieldLen; long lineLen; Cell aCell; Str255 aString; fieldLen = strlen(theField); j = row = col = 0; for (i=0;i<fieldLen;i++) { if ((Byte)theField[i] > 31) { aString[j] = theField[i]; j++; } if ((theField[i] == 13)||(i==(fieldLen-1)) || (theField[i] == ';')) { SetPt(&aCell,col,row); if (theField[i] == 13) { row ++; col = 0; } if (theField[i] == ';') { col ++; j--; } aString[j] = 0; lineLen = strlen((char*)aString); LSetCell(&aString[0], lineLen, aCell, (**gH).theList); j = 0; } }}/* ================ Event Handling ================= *//* These are the Macintosh events that the window can handle. */#define App4Selector(eventPtr) (*((unsigned char *) &(eventPtr)->message))/* top byte of message field is the selector */#define SUSPEND_RESUME_SELECTOR 0x01/* selector of this value is suspend/resume */#define SuspResIsResume(evtMessage) ((evtMessage) & 0x00000001)/* low bit on, signifies resume */#define SuspResIsSuspend(evtMessage) (!SuspResIsResume(evtMessage))/* low bit off, signifies suspend */#define ScrapDataHasChanged(evtMessage) ((evtMessage) & 0x00000002)/* only valid for suspend/resume messages *//* Handle a mouse event. */void DoMouseDown(EventRecord *theEvent){ int windowCode; /* window event code */ Boolean mayBe; /* utility boolean */ WindowPtr whichWindow; /* utility window pointer */ long growResult; /* window grow return */ windowCode = FindWindow(theEvent->where,&whichWindow); /* Respond on the first click */ windowCode = FindWindow(theEvent->where,&whichWindow); /* If we don't float, and we are not in front, come to front. Do not process the mouse click because that will change the selection. */ if ((!(**gH).floats) && (gWindow != FrontDocWindow(gParamPtr)) || ((**gH).floats) && (gWindow != FrontWindow()) ) { SelectWindow(gWindow); return; } /* If we do not have edit, we claim edit. */ if (!(**gH).haveEdit) { ActivateEdit(TRUE); } switch(windowCode) { case inContent: DoInContent(theEvent,whichWindow); break; case inMenuBar: break; case inGoAway: mayBe = TrackGoAway(whichWindow,theEvent->where); if (mayBe==TRUE) { CloseXWindow(gParamPtr,gWindow); /* tell HyperCard that we want to close */ } break; case inGrow: growResult = GrowWindow(whichWindow,theEvent->where,&(**gH).growRect); if (growResult!=0) { MyGrowWindow(whichWindow,growResult); } break; case inZoomIn: case inZoomOut: mayBe = TrackBox(whichWindow,theEvent->where,windowCode); if (mayBe) { SetPort(whichWindow); EraseRect(&whichWindow->portRect); ZoomWindow(whichWindow,windowCode,FALSE); growResult = whichWindow->portRect.right - whichWindow->portRect.left; growResult = growResult + 65536*(whichWindow->portRect.bottom - whichWindow->portRect.top); MyGrowWindow(whichWindow,growResult); } break; case inDrag: gParamPtr->passFlag = TRUE; break; }}</text>
</content>
<name>ListWindow</name>
<script>on openCardhide cd fld "save"pass openCardend openCardon mouseDownInListWIndow windowIDglobal XXLWSelection,gListWindowif windowID is gListWindow thenanswer XXLWSelectionelsepass mouseDownInListWIndowend ifend mouseDownInListWIndowon closeCardif there is a window "ListWindow" thenclose window "ListWindow"end ifend closeCard</script>
</card>
card_6001.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<script>on mouseUpput "EditWindow" into wNameput "50,50,330,200" into wRectput "This is an editable window. Try some typing, etc." into wTextput "false" into wFloatsput "monaco" into wFontput "9" into wSizeput false into lockedEditWindow open,wName,wRect,wText,wFloats,wFont,wSize,locked,CloseEditWindow,40global gEditWindowput the result into gEditWindowif error is in gEditWindow thenanswer gEditWIndowelseshow window id gEditWindowend ifend mouseUp</script>
</part>
<part>
<id>5</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <false /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>286</left>
<top>170</top>
<right>495</right>
<bottom>294</bottom>
</rect>
<style>scrolling</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Geneva</font>
<textSize>9</textSize>
<textStyle>plain</textStyle>
<textHeight>12</textHeight>
<name>save</name>
<script>on mouseUphide meend mouseUp</script>
</part>
<part>
<id>6</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>177</left>
<top>311</top>
<right>249</right>
<bottom>333</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Click Ex.</name>
<script>on mouseUpput "Click Example" into wNameget the rect of the card windowput "10,40,340,140" into wRectput "Command-click on a word here and see it magically appear " into wTextput "in the message box just like it does in a field!. " after wTextput "true" into wFloatsput "Times" into wFontput "18" into wSizeput true into lockedEditWindow open,wName,wRect,wText,wFloats,wFont,wSize,locked,,wrapsglobal gEditWindow2put the result into gEditWindow2if error is in gEditWindow2 thenanswer gEditWindow2elseshow window id gEditWindow2end ifend mouseUp</script>
</part>
<part>
<id>9</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>262</left>
<top>311</top>
<right>431</right>
<bottom>333</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Show C Source</name>
<script>on mouseUplock screenif the short name of me is "Show C Source" thenset the visible of field "source" to trueset the visible of field "more source" to falseset the name of me to "Show C Source: part 2"else if the short name of me is "Show C Source: part 2" thenset the visible of field "more source" to trueset the visible of field "source" to falseset the name of me to "Hide C Source"elseset the visible of field "source" to falseset the visible of field "more source" to falseset the name of me to "Show C Source"end ifunlock screenend mouseUp</script>
</part>
<part>
<id>10</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>18</left>
<top>40</top>
<right>494</right>
<bottom>294</bottom>
</rect>
<style>scrolling</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <true /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Courier</font>
<textSize>10</textSize>
<textStyle>plain</textStyle>
<textHeight>13</textHeight>
<name>prototypes</name>
<script></script>
</part>
<content>
<layer>background</layer>
<id>16</id>
<text><span class="style1">ditWindow XCMD 1.0d2</span><span class="style2">Roger Brown</span><span class="style1">EditWindow </span><span class="style2">is an external window XCMD that creates a fairly simple text-editing window. While this XCMD may be useful in itself, it is included in this stack primarily as an coding example. Many of the features that can be supported by an external window XCMDs are present in the example.EditWindow creates a window with an combination of several properties. Some of these properties are set at the time that the window is created. Others are set using the "set the ... of window ..." syntax in a HyperCard script. Some properties can be set either way.The XCMD understands these direct calls: EditWindow version - returns the version number of the XCMD. EditWindow open, name, rect, text, floating, font, fontSize, lockText, closeFunction, maxCharsPerLine where "open" is the command to open a new window. "name" is the window title. "rect" is the window rect in global screen coordinates. "text" is the text to be displayed in the window. "floating" is true or false "font" is the name of the font to use "fontSize" is the size of the font to use "lockText" is true or false "closeHandler" is the name of a handler to call when the window is closed. "maxCharsPerLine" is a number if you want a fixed limit on the width of characters in the window, or the word "wraps" if you want the text to wrap to fit the window width. None of these parameters except "open" are required. There are default values for all of them: name: EditWindow rect: 70,120,400,300 text: empty floating: false font: monaco fontSize: 9 closeHandler: empty maxCharsPerLine: 80 EditWindow "open" returns the ID of the new window or error messages.Windows are created invisible so that you can adjust the properties before showing them. To open and show a window, use this syntax: EditWindow Open,... other paramters.. put the result into windowID -- adjust properties here show window id windowIDYou can create any number of windows with EditWindow. They can all have the same name if you like. Each will have a unique id, however. Each window can have different properties. EditWindow does not support styled text. EditWindow understands the following "send" messages: - hilite line start stop hilites the lines in the range of start to stop ex. send "hilite Line 1 5" to window "MyWindow" - hilite char start stop hilites the characters in the range of start to stop ex. send "hilite char 1 5" to window "MyWindow" You can </span><span class="style1">set</span><span class="style2"> these properties: - visible - rect - loc - text: eg. set the text of window id windowID to field "summary" - appendtext: appends the given text to the text already in the window - selText: selects some text. Eg. set the seltext of window id windowID to 1,10 - lockText: true or false, if true the user cannot type in the window - textFont - textSize You can </span><span class="style1">get</span><span class="style2"> these properties: - visible - rect - loc - text: eg. put the text of window id windowID into field "user typing" - selText: selects some text. Eg. get the seltext of window id windowID - lockText: true or false, if true the user cannot type in the window - textFont - textSize - numLines: number of lines of text in the window - textChanged: true or false, has the user changed the text by typing? The "closeFunction" parameter allows you to specify a function to be evaluated when the user clicks on the close box. That function must be in the current message hierarchy when the window is closed. It should accept one parameter which is a boolean that indicates whether or not the text in the window was changed. It must return a boolean that indicates whether or not the window should be allowed to close. This gives you the ability to provide a typical Macintosh document style "Save Changes? dialog and gives you an opportunity to save any typing done in the window when it is closed. See the script of this card for an example.If the lockText property is true, a click in the text area of the window withthe command key held down will select the word that was clicked on send this message to the current card: CommandClickInEditWindow windowID, clickTextREVISION HISTORY1.0d0 10/12/92 First public release.1.0d2 3/31/93 Dispose a dangling handle. 4/14/93 The closeHandler did not work if there were no changes.</span></text>
</content>
<content>
<layer>background</layer>
<id>44</id>
<text>HC2</text>
</content>
<content>
<layer>card</layer>
<id>5</id>
<text>This is an editable window. Try some typing, etc. test</text>
</content>
<content>
<layer>background</layer>
<id>45</id>
<text>New!</text>
</content>
<content>
<layer>background</layer>
<id>36</id>
<text>/* EditWindow *//* External Window example *//* Roger Brown Software Development, Kiewit Computation Center, Dartmouth College © 1992 Trustees of Dartmouth College Written in THINK C™ © 1991 Symantec Corp. version 1.0d2 3/31/93 DisposHandle(screenRectH) 4/14/93 fix call to closeHandler with FALSE EditWindow is an external window XCMD that creates a fairly simple text-editing window. While this XCMD may be useful in itself, it is included in this stack primarily as an coding example. Many of the features that can be supported by an external window XCMDs are present in the example. EditWindow creates a window with an combination of several properties. Some of these properties are set at the time that the window is created. Others are set using the "set the ... of window ..." syntax in a HyperCard script. Some properties can be set either way. The XCMD understands these direct calls: EditWindow version - returns the version number of the XCMD. EditWindow open, name, rect, text, floating, font, fontSize, lockText, closeFunction, maxCharsPerLine where "open" is the command to open a new window. "name" is the window title. "rect" is the window rect in global screen coordinates. "text" is the text to be displayed in the window. "floating" is true or false "font" is the name of the font to use "fontSize" is the size of the font to use "lockText" is true or false "closeFunction" is the name of a function handler to call when the window is closed. "maxCharsPerLine" is a number if you want a fixed limit on the width of characters in the window, or the word "wraps" if you want the text to wrap to fit the window width. None of these parameters except "open" are required. There are default values for all of them: name: EditWindow rect: 70,120,400,300 text: empty floating: false font: monaco fontSize: 9 closeHandler: empty maxCharsPerLine: 80 EditWindow "open" returns the ID of the new window or error messages. Windows are created invisible so that you can adjust the properties before showing them. To open and show a window, use this syntax: EditWindow Open,... other parameters.. put the result into windowID -- adjust properties here show window id windowID You can create any number of windows with EditWindow. They can all have the same name if you like. Each will have a unique id, however. Each window can have different properties. EditWindow does not support styled text. There is a limit of 32K of text. EditWindow understands the following "send" messages: - hilite line start stop hilites the lines in the range of start to stop ex. send "hilite Line 1 5" to window "MyWindow" - hilite char start stop hilites the characters in the range of start to stop ex. send "hilite char 1 5" to window "MyWindow" You can set these properties: - visible - rect - loc - text: eg. set the text of window id windowID to field "summary" - appendtext: appends the given text to the text already in the window - selText: selects some text. Eg. set the seltext of window id windowID to 1,10 - lockText: true or false, if true the user cannot type in the window - textFont - textSize You can get these properties: - visible - rect - loc - text: eg. put the text of window id windowID into field "user typing" - selText: selects some text. Eg. get the seltext of window id windowID - lockText: true or false, if true the user cannot type in the window - textFont - textSize - numLines: number of lines of text in the window - textChanged: true or false, has the user changed the text by typing? The "closeFunction" parameter allows you to specify a function to be evaluated when the user clicks on the close box. That function must be in the current message hierarchy when the window is closed. It should accept one parameter which is a boolean that indicates whether or not the text in the window was changed. It must return a boolean that indicates whether or not the window should be allowed to close. This gives you the ability to provide a typical Macintosh document style "Save Changes? dialog and gives you an opportunity to save any typing done in the window when it is closed. Here is an example: function CloseEditWindow changed if not changed then hide cd btn "scan" exit CloseEditWindow end if answer "Save Changes before closing?" with "Cancel","No","Yes" if it is "No" then return true else if it is "Cancel" then return false end if global gEditWindow get the text of window id gEditWindow put it into cd fld "save window text" return TRUE end CloseEditWindow If the lockText property is true, a click in the text area of the window with the command key held down will select the word that was clicked on send this message to the current card: CommandClickInEditWindow windowID, clickText A note on reentrancy: This XCMD allows reentrancy so that we can support the creation of multiple windows and have updating work correctly. To do this safely, we make sure to protect our global data when we make certain callbacks to HyperCard. The reason for this is that some callbacks can result in events being generated for one of our windows. When that happens, the XCMD is reentered while it is already executing and the data global can change. To protect our globals, we save a copy of each on the stack (in local function variables) and restore them after the callback. Here is some sample code: savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; screenRectH = EvalExpr(gParamPtr,"\pthe screenRect"); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; To build the XCMD: Create a project with this source, OSChecks.c, ANSI-A4, HyperXLib, and MacTraps. Set project type to Code Resource, name EditWindow, ID -1142, type XCMD. REVISION HISTORY 1.0d0 10/12/92 First public release.*//* C library headers needed */#include "stdio.h"#include "ctype.h"#include "string.h"#include "math.h"#include "limits.h"#include "Windows.h"#include "HyperXCmd.h"#include "HCUtilities.c"#include <SetUpA4.h>/* prototypes */#include "EditWindow.h" /* constants */#define VERSION "EditWindow version 1.0d2, © Trustees of Dartmouth College, 1992" #define kSBarSize 16#define kMaxCharsPerRow 80#define kLeftMargin 5#define kTopMargin 5#define downArrow 31 /* down arrow key */#define upArrow 30 /* up arrow key */#define rightArrow 29 /* right arrow key */#define leftArrow 28 /* left arrow key */#define kHeadRoom 2048 /* amount of text to throw away when hit 32K */#define maxchars SHRT_MAX - 1/* globals *//* This structure holds all of the data that we want to keep constant across calls of the XCMD for a certain window. */ typedef struct StaticGlobals{ int pWindowType; Rect pWindowRect; int pFont, pTextSize; Boolean pFloats; Rect growRect; ControlHandle vScroll,hScroll; int visibleLines; TEHandle TEH; Boolean haveEdit; Boolean pLockText; Str255 closeFunction; Boolean textChanged; int maxCharsPerRow; Boolean wraps;}StaticGlobals,*StaticGlobalsP,**StaticGlobalsH;WindowPtr gWindow; /* pointer to the window */XCmdPtr gParamPtr; /* the XCMD block pointer */StaticGlobalsH gH; /* our static global data *//* ======================== Main Entry Point ================ *//* The main entry point for the XCMD dispatches messages or events */pascal void main(paramPtr)XCmdPtr paramPtr ;{ /* we have globals, so manipulate A4 to remember them */ RememberA0(); SetUpA4(); /* remember paramptr globally */ gParamPtr = paramPtr; if(gParamPtr->paramCount == -1) { /* Do a regular Macintosh event */ DoMacEvent(); } else { /* or do an XCMD message call */ DoXCMDCall(); } RestoreA4(); } /* ======================= XCMD call processing =============== *//* Handle a call from a script (except for "send..."). These are the messages that we have defined as valid parameters for an XXCMD call. */void DoXCMDCall(void){ int i; Handle taskHandle; char temp[256]; for (i=0;i<gParamPtr->paramCount;i++) HLock(gParamPtr->params[i]); /* get the opcode */ taskHandle = gParamPtr->params[0]; ucase(*taskHandle); /* branch on the opcode */ if (strcmp(*taskHandle,"VERSION")==0) ReturnVersion(); else if (strcmp(*taskHandle,"OPEN")==0) DoOpenWindow(); else { strcpy((char*)temp,"XWindow Error: unknown message "); strcat((char*)temp,*taskHandle); ResultIs(gParamPtr,temp); }} /* return the version number */void ReturnVersion(void){ ResultIs(gParamPtr,VERSION);}/* Open a window. */void DoOpenWindow(void){ GrafPtr savePort; WindowPtr windPtr; char name[256]; int result; strcpy(name,"EditWindow"); /* default name */ if ((gParamPtr->paramCount > 2) && (strlen(*gParamPtr->params[1]) > 0)) strcpy((char*)name,*gParamPtr->params[1]); result = CreateWindow(name); switch(result) { case xresNotImp: ResultIs(gParamPtr,"Error: External windows not implemented" ) ; break; case xresFail: ResultIs(gParamPtr,"Error: Could not create external window" ) ; break; default : /* return the window pointer */ NumToString((long)gWindow,name); PtoCstr((char*)name); ResultIs(gParamPtr,name) ; break; }}/* Create a new window */int CreateWindow(char *name){ WindowPtr wind; Rect r; int windowType; Str255 s; CreateStaticGlobals(); if (gH == NULL) { return xresFail; } GetWindowParameters(); /* set other window parameters or defaults */ strcpy((char*)s,name); CtoPstr((char*)s); windowType = (**gH).pWindowType; /* Create the window invisble. Show it from a script. This lets us set properties before it is first shown. */ wind = NewXWindow(gParamPtr,&(**gH).pWindowRect,s,FALSE,windowType,FALSE,(**gH).pFloats); if( gParamPtr->result != xresSucc) { DisposHandle(gH); } else { gWindow = wind; XCMDInitWindow(); } return gParamPtr->result;} /* ===================== Mac event processing ====================== *//* process a Macintosh event */void DoMacEvent(void){ GrafPtr savePort ; EventRecord event ; /* what window is this for? */ gParamPtr->passFlag = FALSE ; gWindow = ((XWEventInfoPtr)(gParamPtr->params[0]))->eventWindow; /* load the window's globals */ LoadStaticGlobals(); /* get the event */ event = ((XWEventInfoPtr)(gParamPtr->params[0]))->event; GetPort(&savePort) ; SetPort(gWindow) ; /* do the event */ DispatchMacEvent(&event ) ; SetPort(savePort); } /* dispatch a Macintosh event */void DispatchMacEvent(EventRecord *evt ){ switch( evt->what ) { case mouseDown: DoMouseDown(evt); break; case updateEvt: DoUpdate(); break; case xCursorWithin: CheckCursor(); break; case xOpenEvt: DoOpenEvent(); break; case xCloseEvt: DoCloseEvent(); break ; case keyDown: case autoKey: DoKeyEvent(evt); break; case activateEvt: DoActivateEvent(evt); break; case app4Evt: HandleApp4Evt(evt); break; case xGiveUpEditEvt: ActivateEdit(FALSE); break; case xEditUndo: break; case xEditCut: DoEditCut(); break; case xEditCopy: DoEditCopy(); break; case xEditPaste: DoEditPaste(); break; case xEditClear: DoEditClear(); break; case xSendEvt: DoSendEvent(); break; case xSetPropEvt: SetProperty(); break; case xGetPropEvt: GetProperty(); break; case xHidePalettesEvt: HideWindow(gWindow); break; case xShowPalettesEvt: ShowWindow(gWindow); break; case nullEvent: DoNullEvent(); break; default : break; } } /* ================== Initialization ================ *//* Parse out the window parameters sent from HyperTalk, use defaults for those that are not defined. */void GetWindowParameters(void){ Str255 s; long n; int i; /* window defaults */ #define cWRLeft 70 #define cWRTop 120 #define cWRRight 416 #define cWRBottom 300 #define cFont monaco #define cTextSize 9 (**gH).pWindowType = zoomDocProc; (**gH).TEH = NULL; (**gH).textChanged = FALSE; /* param[1] has the window name */ /* param[2] has the window rect */ /* param[3] has the text to display */ /* param[4] has the floating flag */ /* param[5] has the font */ /* param[6] has the font size */ /* param[7] has the lockText */ /* param[8] has the name of a close function */ /* param[9] has the maxCharsPerRow parameter */ /* check for a rectangle parameter */ if ((gParamPtr->paramCount > 2)&&(strlen(*gParamPtr->params[2]) > 0)) { CtoPstr(*gParamPtr->params[2]); StrToRect(gParamPtr,(StringPtr)*gParamPtr->params[2],&(**gH).pWindowRect); } else SetRect(&(**gH).pWindowRect,cWRLeft,cWRTop,cWRRight,cWRBottom); /* size is hard wired */ /* check for "floats" flag */ (**gH).pFloats = false; if (gParamPtr->paramCount > 4) { ucase(*gParamPtr->params[4]); if (strcmp(*gParamPtr->params[4],"TRUE")==0) { (**gH).pFloats = TRUE; (**gH).pWindowType = palZoomProc+hasTallTBar; } } /* check for a font name */ (**gH).pFont = cFont; if (gParamPtr->paramCount > 5) { strcpy((char*)s,*gParamPtr->params[5]); if (strlen((char*)s) > 0) { CtoPstr(s); GetFNum(s,&i); (**gH).pFont = i; } } /* check for font size */ (**gH).pTextSize = cTextSize; if (gParamPtr->paramCount > 6) { strcpy((char*)s,*gParamPtr->params[6]); if (strlen((char*)s) > 0) { if (IsNumber((char*)s,&n)) (**gH).pTextSize = n; } } /* check for lock text */ (**gH).pLockText = FALSE; if (gParamPtr->paramCount > 7) { strcpy((char*)s,*gParamPtr->params[7]); if (strlen((char*)s) > 0) { CtoPstr(s); if (EqualString(s,"\pTRUE",FALSE,FALSE)) (**gH).pLockText = TRUE; else if (EqualString(s,"\pFALSE",FALSE,FALSE)) (**gH).pLockText = FALSE; } } /* check for a close function */ (**gH).closeFunction[0] = 0; if (gParamPtr->paramCount > 8) { strcpy((char*)(**gH).closeFunction,*gParamPtr->params[8]); } /* check for a max chars per row */ (**gH).maxCharsPerRow = kMaxCharsPerRow; (**gH).wraps = FALSE; if (gParamPtr->paramCount > 9) { strcpy((char*)s,*gParamPtr->params[9]); if (IsNumber((char*)s,&n)) (**gH).maxCharsPerRow = n; else { ucase((char*)s); (**gH).wraps = (strcmp((char*)s,"WRAPS") == 0); } }}/* Initialize the window. */void XCMDInitWindow(void){ int width,height; /* rect dimensions */ Rect r; /* utility rect */ Rect vRect,dRect; /* TE rects */ Handle screenRectH; /* handle to the screen rect from HC */ XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; /* remember the globals handle */ ((WindowPeek)gWindow)->refCon = (long)gH; /* initialize scrolling */ r = gWindow->portRect; width = r.right - r.left; InitEditing(); dRect = (**(**gH).TEH).destRect; vRect = (**(**gH).TEH).viewRect; /* set up vertical scroll bar */ r = gWindow->portRect; r.top--; r.left = r.right-kSBarSize+1; r.right += 1; r.bottom = r.bottom - kSBarSize + 2; (**gH).vScroll = NewControl( gWindow, &r, "\p", true, 0, 0, 0,scrollBarProc, 0L); MoveHHi((**gH).vScroll); HLock((**gH).vScroll); /* set up horizontal scroll bar */ r = gWindow->portRect; r.left -= 1; r.bottom += 1; r.right -= kSBarSize - 2; r.top = r.bottom - kSBarSize; (**gH).hScroll = NewControl( gWindow, &r, "\p", true, 0, 0, 0,scrollBarProc, 0L); MoveHHi((**gH).hScroll); HLock((**gH).hScroll); /* get grow limit */ /* See callback protection note at top of file */ savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; screenRectH = EvalExpr(gParamPtr,"\pthe screenRect"); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; CtoPstr(*screenRectH); StrToRect(gParamPtr,(StringPtr)*screenRectH,&r); (**gH).growRect = r; (**gH).growRect.right = r.right - r.left; (**gH).growRect.bottom = r.bottom - r.top; (**gH).growRect.left = 200; (**gH).growRect.top = 60; SetZoomRect(&r); DisposHandle(screenRectH);}/* Set the window zoom rect. */void SetZoomRect(Rect *screenRect){ WStateData *ws; WindowPeek wp; Handle dh; Rect zoomRect; wp = (WindowPeek)gWindow; dh = wp->dataHandle; ws = (WStateData *)(*dh); zoomRect = *screenRect; InsetRect(&zoomRect,3,3); zoomRect.top += 40; ws->stdState = zoomRect;}/* ================ Event Handling ================= *//* These are the Macintosh events that the window can handle. */#define App4Selector(eventPtr) (*((unsigned char *) &(eventPtr)->message))/* top byte of message field is the selector */#define SUSPEND_RESUME_SELECTOR 0x01/* selector of this value is suspend/resume */#define SuspResIsResume(evtMessage) ((evtMessage) & 0x00000001)/* low bit on, signifies resume */#define SuspResIsSuspend(evtMessage) (!SuspResIsResume(evtMessage))/* low bit off, signifies suspend */#define ScrapDataHasChanged(evtMessage) ((evtMessage) & 0x00000002)/* only valid for suspend/resume messages *//* Handle a mouse event. */void DoMouseDown(EventRecord *theEvent){ int windowCode; /* window event code */ Boolean mayBe; /* utility boolean */ WindowPtr whichWindow; /* utility window pointer */ long growResult; /* window grow return */ windowCode = FindWindow(theEvent->where,&whichWindow); /* Respond on the first click */ windowCode = FindWindow(theEvent->where,&whichWindow); /* any mouse down brings us to the front and turns on edit. If we are a floater then we come all the way front, else we come to the front of the document layer. */ if ((!(**gH).pFloats) && (gWindow != FrontDocWindow(gParamPtr)) || ((**gH).pFloats) && (gWindow != FrontWindow()) ) { SelectWindow(gWindow); } /* If we do not have edit, we claim edit. If there is a selection, and this click is in the typing area, and we are not locked, we preserve the selection by returning now. Otherwise we handle the click. */ if (!(**gH).haveEdit) { ActivateEdit(TRUE); if (!SelectionEmpty() && (PtInRect(theEvent->where,&(**(**gH).TEH).viewRect)) && (!(**gH).pLockText)) return; } switch(windowCode) { case inContent: DoInContent(theEvent,whichWindow); break; case inMenuBar: break; case inGoAway: mayBe = TrackGoAway(whichWindow,theEvent->where); if (mayBe==TRUE) { CloseXWindow(gParamPtr,gWindow); /* tell HyperCard that we want to close */ } break; case inDrag: gParamPtr->passFlag = TRUE; break; case inGrow: growResult = GrowWindow(whichWindow,theEvent->where,&(**gH).growRect); if (growResult!=0) { MyGrowWindow(whichWindow,growResult); } break; case inZoomIn: case inZoomOut: mayBe = TrackBox(whichWindow,theEvent->where,windowCode); if (mayBe) { SetPort(whichWindow); EraseRect(&whichWindow->portRect); ZoomWindow(whichWindow,windowCode,FALSE); growResult = whichWindow->portRect.right - whichWindow->portRect.left; growResult = growResult + 65536*(whichWindow->portRect.bottom - whichWindow->portRect.top); MyGrowWindow(whichWindow,growResult); } break; }}/* Do an update event. */void DoUpdate(void){ GrafPtr gp; /* We already set the port. */ BeginUpdate(gWindow); EraseRect(&gWindow->portRect); DrawWindow(); EndUpdate(gWindow);}/* Show I-beam cursor if appropriate. */void CheckCursor(void){ Point mp; Rect r; GetMouse(&mp); r = (**(**gH).TEH).viewRect; if ( (!(**gH).haveEdit) || (!PtInRect(mp,&r)) ) { InitCursor(); return; } if (!(**gH).pLockText) SetIBeam();}/* Handle an open event. */void DoOpenEvent(void){ SetXWIdleTime(gParamPtr,gWindow,30L); /* we need idle tme to blink indertion bar */ XWAllowReEntrancy(gParamPtr,gWindow,TRUE,TRUE); /* and allow reentrancy for update events */ if ((**gH).pFloats) { /* If we float, grab edit control and set ibeam */ ActivateEdit(TRUE); TESetSelect(0,0,(**gH).TEH); } ShowSelection(); /* set up scroll bars */}/* Handle a close event */void DoCloseEvent(void){ int r,c; char s1[256]; Handle h; Boolean okToClose = TRUE; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; if (gWindow == NULL) return; /* This can happen, really. */ /* Run the close function if there is one. It tells us if we should really close. */ if ((**gH).closeFunction[0] != 0) { savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; /* Call the function with the value of the changed parameter. */ strcpy(s1,(char*)(**gH).closeFunction); if ((**gH).textChanged) strcat(s1,"(TRUE)"); else strcat(s1,"(FALSE)"); CtoPstr(s1); h = EvalExpr(gParamPtr,(StringPtr)s1); if (h != NULL) { strcpy(s1,*h); ucase(s1); if (strcmp(s1,"FALSE")==0) okToClose = FALSE; DisposeHandle(h); } gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; } /* Procede with close if user says to. */ gParamPtr->passFlag = okToClose; if (!okToClose) return; /* Clean up memory allocations. */ ActivateEdit(FALSE); DisposeControl((**gH).vScroll); DisposeControl((**gH).hScroll); TEDispose((**gH).TEH); DisposHandle(gH); gWindow = NULL;}/* Handle a key event */void DoKeyEvent(EventRecord *theEvent){ int code; Boolean arrowKey = FALSE; int saveStart,saveEnd; code = BitAnd(theEvent->message,charCodeMask); /* what keys was pressed? */ /* check command keys */ if ((theEvent->modifiers & cmdKey) != 0) return; if ((code==8)&&(!SelectionEmpty())) { DoEditCut(); return; } if ((code < downArrow+1) && code > (leftArrow-1)) arrowKey = TRUE; /* Accept characters if we can edit or it it's an arrow key. */ if (!(**gH).pLockText || arrowKey) { if ((**(**gH).TEH).teLength == maxchars) { TooMuchText(); saveStart = (**(**gH).TEH).selStart; saveEnd = (**(**gH).TEH).selEnd; TESetSelect(0,kHeadRoom,(**gH).TEH); TEDelete((**gH).TEH); TESetSelect(saveStart - kHeadRoom, saveEnd - kHeadRoom,(**gH).TEH); } TEKey(code,(**gH).TEH); ShowSelection(); (**gH).textChanged = !arrowKey; }}/* Handle an activate event. */void DoActivateEvent(EventRecord *theEvent){ OSErr err; if (theEvent->modifiers & activeFlag ) { /* activate */ err = TEFromScrap(); /* import the scrap */ HiliteControl((**gH).vScroll,0); /* enable scroll bars */ HiliteControl((**gH).hScroll,0); /* enable editing */ ActivateEdit(TRUE); } else { err = ZeroScrap(); /* export the scrap */ if (err==noErr) err = TEToScrap(); if (!(**gH).pFloats) { /* if we don't float, disable scroll bars */ HiliteControl((**gH).vScroll,255); HiliteControl((**gH).hScroll,255); } ActivateEdit(FALSE); /* turn off edit */ }}/* Handle the app4 event if and only if its a suspend/resume event *//* The only action we take is to convert the scrap to and from the public scrap */void HandleApp4Evt(EventRecord *theEvent){ OSErr err; if (App4Selector(theEvent) == SUSPEND_RESUME_SELECTOR) { if SuspResIsSuspend(theEvent->message) { if (ScrapDataHasChanged(theEvent->message)) { err = ZeroScrap(); err = TEToScrap(); /* convert the scrap */ } if (!(**gH).pFloats) { /* disable scroll bars if not floating */ HiliteControl((**gH).vScroll,255); HiliteControl((**gH).hScroll,255); } else HideWindow(gWindow); /* if floats, hide it */ ActivateEdit(FALSE); } else { if (ScrapDataHasChanged(theEvent->message)) { err = TEFromScrap(); /* convert the scrap */ } ShowWindow(gWindow); /* show window */ if ((**gH).haveEdit) ActivateEdit(TRUE); /* hilite the selection */ } }}/* So, we are lazy about undo. Rainy day project. */void DoEditUndo(void){}/* Cut text if not locked. */void DoEditCut(void){ if (!(**gH).pLockText) { TECut((**gH).TEH); (**gH).textChanged = TRUE; ShowSelection(); } else SysBeep(0);} /* Copy text. */void DoEditCopy(void){ if (!SelectionEmpty()) { TECopy((**gH).TEH); }}/* Paste text if not locked. */void DoEditPaste(void){ long len; PScrapStuff info; int saveStart,saveEnd; if (!(**gH).pLockText) { info = InfoScrap(); if ((**(**gH).TEH).teLength + info->scrapSize > maxchars) { TooMuchText(); saveStart = (**(**gH).TEH).selStart; saveEnd = (**(**gH).TEH).selEnd; TESetSelect(0,info->scrapSize + kHeadRoom,(**gH).TEH); TEDelete((**gH).TEH); TESetSelect(saveStart - info->scrapSize + kHeadRoom, saveEnd - info->scrapSize + kHeadRoom,(**gH).TEH); } TEPaste((**gH).TEH); (**gH).textChanged = TRUE; ShowSelection(); } else SysBeep(0);}</text>
<text><span class="style5">/* Clear selection if not locked. */void DoEditClear(void){ if (!(**gH).pLockText) { TEDelete((**gH).TEH); (**gH).textChanged = TRUE; ShowSelection(); } else SysBeep(0);}/* Handle a "send" message. */void DoSendEvent(void){ char *message; XWEventInfoPtr theInfo; long n1,n2; char s[256]; /* Get the message text. Its a P String. */ theInfo = (XWEventInfoPtr)gParamPtr->params[0]; message = (char*)(Handle)(theInfo->eventParams[0]); UprString(message,TRUE); PtoCstr(message); /* Syntax: HILITE LINE START FINISH or HILITE CHAR START FINISH */ if (StrContains(message,"HILITE")) { pickoff(message,' ',s); /* strip first word */ pickoff(message,' ',s); /* get second word */ ucase((char*)s); if (strcmp((char*)s,"LINE") == 0) { pickoff(message,' ',s); /* Get start parameter */ if (IsNumber(s,&n1)) { pickoff(message,' ',s); /* Get finish parameter. Use -1 if none. */ if (IsNumber(s,&n2)) { HiliteLines(n1,n2); } else HiliteLines(n1,-1L); } } else if (strcmp((char*)s,"CHAR") == 0) { pickoff(message,' ',s); /* Get start parameter */ if (IsNumber(s,&n1)) { pickoff(message,' ',s); /* Get finish parameter. Use -1 if none. */ if (IsNumber(s,&n2)) { HiliteChars(n1,n2); } else HiliteChars(n1,-1L); } } }} /* Handle a NULL event: just blink the insertion bar if appropriate. */ void DoNullEvent(void){ XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; if ((**gH).haveEdit) { ActivateEdit(TRUE); if (!(**gH).pLockText) { if (!(**gH).pLockText) TEIdle((**gH).TEH); } }}/* Set the cursor to an IBeam. */void SetIBeam(void){ /* This message should not cause reentrance */ SendHCMessage(gParamPtr,"\pset the cursor to ibeam");}/* Handle mouse events in window content region */void DoInContent(EventRecord *theEvent,WindowPtr theWindow){ int partCode; /* control part */ ControlHandle theControl; /* the control hit */ char extended; /* extended selection flag */ GlobalToLocal(&theEvent->where); partCode = FindControl(theEvent->where,theWindow,&theControl); /* in a scroll bar */ if ((theControl==(**gH).vScroll)|| (theControl==(**gH).hScroll)) { if (partCode == inThumb) { partCode = TrackControl(theControl,theEvent->where,NULL); AdjustText(); } else { if (theControl==(**gH).vScroll) { partCode = TrackControl(theControl,theEvent->where,VScrollProc); } else { partCode = TrackControl(theControl,theEvent->where,HScrollProc); } } } else if (partCode==0) { /* in text area */ if (!PtInRect(theEvent->where,&(**(**gH).TEH).viewRect)) return; if ( ((**gH).pLockText) && (BitAnd(theEvent->modifiers,cmdKey)!=0)) { DoCommandClick(theEvent->where); return; } extended = (BitAnd(theEvent->modifiers,shiftKey)!=0); ClipRect(&gWindow->portRect); /* so can't drag/select over scrollers */ (**(**gH).TEH).clikLoop = (ProcPtr)ScrollUpdater; RememberA4(); TEClick(theEvent->where,extended,(**gH).TEH); /* always give event to TE */ ClipRect(&gWindow->portRect); /* restore full clip so controls are redrawn */ } }void DoCommandClick(Point mp){ Handle h; char s1[256],s2[256]; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; TEClick(mp,false,(**gH).TEH); TEClick(mp,false,(**gH).TEH); h = GetWindowSelectedText(); strcpy(s1,"CommandClickInEditWindow "); NumToString((long)gWindow,s2); PtoCstr(s2); strcat(s1,s2); strcat(s1,",\""); strcat(s1,*h); strcat(s1,"\""); DisposHandle(h); CtoPstr(s1); savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; SendCardMessage(gParamPtr,(StringPtr)s1); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH;}/* =============== Window Management ================ *//* Draw the window. */void DrawWindow(void){ Rect r; Str255 title; SetPort(gWindow); r = gWindow->portRect; ClipRect(&r); EraseRect(&r); TEUpdate(&r,(**gH).TEH); DrawControls(gWindow); DrawGrowIcon(gWindow);}/* Resize the window. */void MyGrowWindow(WindowPtr window,long result){ int newWidth,newHeight; Rect r; SetPort(gWindow); r = gWindow->portRect; EraseRect(&r); newWidth = (int)LoWord(result); newHeight = HiWord(result); SizeWindow(window,newWidth,newHeight,TRUE); /* set up vertical scroll bar */ r = gWindow->portRect; r.top--; r.left = r.right-kSBarSize+1; r.right += 1; r.bottom = r.bottom - kSBarSize + 1; HideControl((**gH).vScroll); MoveControl((**gH).vScroll,r.left,r.top); SizeControl((**gH).vScroll,kSBarSize, r.bottom - r.top + 1); ShowControl((**gH).vScroll); /* set up horizontal scroll bar */ r = gWindow->portRect; r.left -= 1; r.bottom += 1; r.right -= kSBarSize - 2; r.top = r.bottom - kSBarSize; HideControl((**gH).hScroll); MoveControl((**gH).hScroll,r.left,r.top); SizeControl((**gH).hScroll, r.right - r.left,kSBarSize); ShowControl((**gH).hScroll); SetView(); SetVScroll(); SetHScroll(); AdjustText(); r = gWindow->portRect; InvalRect(&r); BeginUpdate(gWindow); DrawWindow(); EndUpdate(gWindow);}/* Scroll the dest rect to match the current scroll values. */int AdjustText (void){ int oldScroll, newScroll, deltaH,deltaV; oldScroll = (**(**gH).TEH).viewRect.top - (**(**gH).TEH).destRect.top; newScroll = GetCtlValue((**gH).vScroll) * (**(**gH).TEH).lineHeight; deltaV = oldScroll - newScroll; oldScroll = (**(**gH).TEH).viewRect.left - (**(**gH).TEH).destRect.left; newScroll = GetCtlValue((**gH).hScroll) * CharWidth('w'); deltaH = oldScroll - newScroll; if ((deltaV != 0) || (deltaH != 0)) { TEScroll(deltaH, deltaV, (**gH).TEH); }}/* Set the horizontal scroll max value. */void SetHScroll(void){ register int n; Rect r1,r2; int cWidth; r1 = (**(**gH).TEH).destRect; r2 = gWindow->portRect; cWidth = CharWidth('w'); n = (r1.right - r1.left)/cWidth - (r2.right - r1.left - kSBarSize)/cWidth; SetCtlMax((**gH).hScroll, n > 0 ? n : 0);}/* Set the vertical scroll max value. */void SetVScroll(void){ register int n; n = (**(**gH).TEH).nLines-(**gH).visibleLines; if ((**(**gH).TEH).teLength > 0 && (*((**(**gH).TEH).hText))[(**(**gH).TEH).teLength-1]=='\r') n++; SetCtlMax((**gH).vScroll, n > 0 ? n : 0);}/* Clikloop routine for updating the scroll controls while drag selecting. */pascal Boolean ScrollUpdater(void){ Point mp; Rect vRect; SetUpA4(); GetMouse(&mp); vRect = (**(**gH).TEH).viewRect; if (!PtInRect(mp,&vRect)) { /* has scrolled */ ClipRect(&gWindow->portRect); /* update the controls */ if (mp.v < (**(**gH).TEH).viewRect.top+kLeftMargin) { SetCtlValue((**gH).vScroll, GetCtlValue((**gH).vScroll) - 1); } else if (mp.v > (**(**gH).TEH).viewRect.bottom-kLeftMargin){ SetCtlValue((**gH).vScroll, GetCtlValue((**gH).vScroll) + 1); } if (mp.h < (**(**gH).TEH).viewRect.left+kLeftMargin) { SetCtlValue((**gH).hScroll, GetCtlValue((**gH).hScroll) - 1); } else if (mp.h > (**(**gH).TEH).viewRect.right-kLeftMargin){ SetCtlValue((**gH).hScroll, GetCtlValue((**gH).hScroll) + 1); } ClipRect(&(**(**gH).TEH).viewRect); AdjustText(); } RestoreA4(); return TRUE;}/* Make the current selection visible. */void ShowSelection (void){ register int topLine, bottomLine, theLine; Point sPt; int textWidth; /* set the scroll values and maximums. */ SetVScroll(); SetHScroll(); AdjustText(); /* Now scroll selection start into view. */ topLine = GetCtlValue((**gH).vScroll); bottomLine = topLine + (**gH).visibleLines; if ((**(**gH).TEH).selStart < (**(**gH).TEH).lineStarts[topLine] || (**(**gH).TEH).selStart >= (**(**gH).TEH).lineStarts[bottomLine]) { for (theLine = 0; (**(**gH).TEH).selStart >= (**(**gH).TEH).lineStarts[theLine]; theLine++) ; SetCtlValue((**gH).vScroll, theLine - (**gH).visibleLines); AdjustText(); } sPt = TEGetPoint((**(**gH).TEH).selStart,(**gH).TEH); if (!PtInRect(sPt,&(**(**gH).TEH).viewRect)) { textWidth = (**(**gH).TEH).viewRect.right - (**(**gH).TEH).viewRect.left - 2*kLeftMargin; if (sPt.h < (**(**gH).TEH).viewRect.left+kLeftMargin) { SetCtlValue((**gH).hScroll, GetCtlValue((**gH).hScroll) + sPt.h/CharWidth('w') - 1); } else { SetCtlValue((**gH).hScroll, GetCtlValue((**gH).hScroll) + (sPt.h - textWidth)/CharWidth('w')); } AdjustText(); }}/* Vertical scroll bar action procedure. */pascal void VScrollProc (ControlHandle theControl, int theCode){ int pageSize; int scrollAmt; int oldCtl; if (theCode == 0) return ; pageSize = ((**(**gH).TEH).viewRect.bottom-(**(**gH).TEH).viewRect.top) / (**(**gH).TEH).lineHeight - 1; switch (theCode) { case inUpButton: scrollAmt = -1; break; case inDownButton: scrollAmt = 1; break; case inPageUp: scrollAmt = -pageSize; break; case inPageDown: scrollAmt = pageSize; break; } oldCtl = GetCtlValue(theControl); SetCtlValue(theControl, oldCtl+scrollAmt); AdjustText();}/* Horizontal scroll bar action procedure. */pascal void HScrollProc (ControlHandle theControl, int theCode){ int pageSize; int scrollAmt; int oldCtl; if (theCode == 0) return ; pageSize = ((**(**gH).TEH).viewRect.right-(**(**gH).TEH).viewRect.left) / CharWidth('w') - 1; switch (theCode) { case inUpButton: scrollAmt = -1; break; case inDownButton: scrollAmt = 1; break; case inPageUp: scrollAmt = -pageSize; break; case inPageDown: scrollAmt = pageSize; break; } oldCtl = GetCtlValue(theControl); SetCtlValue(theControl, oldCtl+scrollAmt); AdjustText();}/* Set TE rectangles and calc the text to fit. */void SetView (void){ Rect r; int width; r = gWindow->portRect; width = r.right - r.left; (**(**gH).TEH).viewRect = r; (**(**gH).TEH).viewRect.right -= kSBarSize; (**(**gH).TEH).viewRect.bottom -= kSBarSize; InsetRect(&(**(**gH).TEH).viewRect, kLeftMargin, kTopMargin); (**gH).visibleLines = ((**(**gH).TEH).viewRect.bottom- (**(**gH).TEH).viewRect.top)/(**(**gH).TEH).lineHeight; (**(**gH).TEH).viewRect.bottom = (**(**gH).TEH).viewRect.top + (**(**gH).TEH).lineHeight*(**gH).visibleLines; if ((**gH).wraps) (**(**gH).TEH).destRect.right = (**(**gH).TEH).viewRect.right; TECalText((**gH).TEH);}/* =============== Text Editing ============== *//* Initialize TE structures */void InitEditing(void){ FontInfo fi; /* font spacing information */ int lineHeight; /* height of line in this font */ Rect r; int nLines; /* set the font */ SetPort(gWindow); TextFont((**gH).pFont); TextSize((**gH).pTextSize); /* set the view and dest rects */ if (gParamPtr->paramCount > 3) nLines = NumHCLines(*gParamPtr->params[3]); else nLines = 1; GetFontInfo(&fi); lineHeight = fi.ascent + fi.descent + fi.leading; SetRect(&r,kLeftMargin,kTopMargin, 4*kLeftMargin+CharWidth('w')*(**gH).maxCharsPerRow,32000); (**gH).TEH = TENew(&r,&(**(**gH).TEH).viewRect); MoveHHi((**gH).TEH); HLock((**gH).TEH); if (gParamPtr->paramCount > 3) { TESetText(*gParamPtr->params[3],strlen(*gParamPtr->params[3]),(**gH).TEH); } ActivateEdit(FALSE); SetView();}/* Is the current selection empty? */Boolean SelectionEmpty(void){ return ((**(**gH).TEH).selEnd == (**(**gH).TEH).selStart);}/* Turn editing on or off. */void ActivateEdit(Boolean activate){ OSErr err; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; if (gWindow==NULL) return; SetPort(gWindow); ClipRect(&gWindow->portRect); if (activate) { savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; BeginXWEdit(gParamPtr,gWindow); /* get edit control */ gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; TEActivate((**gH).TEH); /* activate TE */ (**gH).haveEdit = TRUE; } else { savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; EndXWEdit(gParamPtr,gWindow); /* give up edit control */ gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; TEDeactivate((**gH).TEH); /* deactivate TE */ (**gH).haveEdit = FALSE; /* export the scrap in case some other editable window wants it */ err = ZeroScrap(); if (err==noErr) err = TEToScrap(); } }void TooMuchText(void){ XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; ShowHCAlert(gParamPtr,1, "\pEditwindow cannot accept this many characters. Some will be deleted at the beginning."); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; }/* =================== Window Properties and Messages =================== *//* Format a proerty value expressed as a string. */Handle FormatProperty(char *s){ long len; Handle h; len = 1+strlen(s); h = NewHandle(len); BlockMove(s,*h,len); return h;}/* Get the text of the window. */Handle GetWindowText(void){ long len; Handle theData; len = 1 + (**(**gH).TEH).teLength; theData = NewHandle(len); if (theData == NULL) return theData; BlockMove(*(**(**gH).TEH).hText,*theData,len-1); *(*theData+len-1) = 0; return theData;}/* Get the selected text of the window. */Handle GetWindowSelectedText(void){ long len; Handle theData; Ptr p; len = (**(**gH).TEH).selEnd - (**(**gH).TEH).selStart + 1; theData = NewHandle(len); if (theData == NULL) return theData; p = *(**(**gH).TEH).hText; p = p + (**(**gH).TEH).selStart; BlockMove(p,*theData,len-1); *(*theData+len-1) = 0; return theData;}/* get the requested property. */void GetProperty(void){ char *message; XWEventInfoPtr theInfo; char numStr[256],prop[256]; int error; Rect r1,r2; Point p; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; theInfo = (XWEventInfoPtr)gParamPtr->params[0]; message = (char*)(Handle)(theInfo->eventParams[0]); PtoCstr(message); strcpy(prop,message); CtoPstr(prop); UprString(prop,TRUE); gParamPtr->passFlag = FALSE; if (EqualString(prop,"\pVISIBLE",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(prop,"\pLOC",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(prop,"\pRECT",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(prop,"\pTEXT",FALSE,FALSE)) { theInfo->eventResult = GetWindowText(); return; } if (EqualString(prop,"\pSELTEXT",FALSE,FALSE)) { theInfo->eventResult = GetWindowSelectedText(); return; } if (EqualString(prop,"\pLOCKTEXT",FALSE,FALSE)) { if ((**gH).pLockText) strcpy(message,"TRUE"); else strcpy(message,"FALSE"); theInfo->eventResult = FormatProperty(message); return; } if (EqualString(prop,"\pTEXTFONT",FALSE,FALSE)) { GetFontName((**gH).pFont,message); PtoCstr((char*)message); theInfo->eventResult = FormatProperty(message); return; } if (EqualString(prop,"\pTEXTSIZE",FALSE,FALSE)) { NumToString((long)((**gH).pTextSize),message); PtoCstr((char*)message); theInfo->eventResult = FormatProperty(message); return; } if (EqualString(prop,"\pNUMLINES",FALSE,FALSE)) { NumToString((long)(**(**gH).TEH).nLines,message); PtoCstr((char*)message); theInfo->eventResult = FormatProperty(message); return; } if (EqualString(prop,"\pTEXTCHANGED",FALSE,FALSE)) { if ((**gH).textChanged) strcpy(message,"TRUE"); else strcpy(message,"FALSE"); theInfo->eventResult = FormatProperty(message); return; }}/* Set the requested property. */void SetProperty(void){ char *message; XWEventInfoPtr theInfo; Rect r1,r2; char s[256],num[256]; long start,end,n; int i; long growResult; Point p; long len,teLen; XCmdPtr savePtr; WindowPtr saveWindow; StaticGlobalsH saveGH; FontInfo fi; theInfo = (XWEventInfoPtr)gParamPtr->params[0]; message = (char*)(Handle)(theInfo->eventParams[0]); PtoCstr(message); strcpy(s,message); CtoPstr(s); UprString(s,TRUE); gParamPtr->passFlag = FALSE; if (EqualString(s,"\pVISIBLE",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(s,"\pLOC",FALSE,FALSE)) { gParamPtr->passFlag = TRUE; /* HC does this for us. */ return; } if (EqualString(s,"\pRECT",FALSE,FALSE)) { strcpy(s,*(Handle)(theInfo->eventParams[1])); CtoPstr(s); StrToRect(gParamPtr,(StringPtr)s,&r1); /* We do this ourselves to grow the window correctly. */ /* move the window to proper global location */ savePtr = gParamPtr; saveWindow = gWindow; saveGH = gH; GetCardRect(gParamPtr,&r2); gParamPtr = savePtr; gWindow = saveWindow; gH = saveGH; p.h = r1.left + r2.left; p.v = r1.top + r2.top; MoveWindow(gWindow,p.h,p.v,FALSE); /* grow the window to the proper global coordinate */ p.h = r1.right - r1.left; p.v = r1.bottom - r1.top; r2 = (**gH).growRect; p.h = max(min(p.h,r2.right),r2.left); p.v = max(min(p.v,r2.bottom),r2.top); growResult = p.v; growResult = BitShift(growResult,16) + p.h; MyGrowWindow(gWindow,growResult); return; } if (EqualString(s,"\pTEXT",FALSE,FALSE)) { HLock((Handle)(theInfo->eventParams[1])); len = strlen(*(Handle)(theInfo->eventParams[1])); if (len > maxchars) { /* We can only accept this much. */ len = maxchars; TooMuchText(); } TESetText(*(Handle)(theInfo->eventParams[1]),len,(**gH).TEH); TESetSelect(0L,0L,(**gH).TEH); SetView(); ShowSelection(); (**gH).textChanged = FALSE; InvalRect(&gWindow->portRect); return; } if (EqualString(s,"\pAPPENDTEXT",FALSE,FALSE)) { HLock((Handle)(theInfo->eventParams[1])); len = strlen(*(Handle)(theInfo->eventParams[1])); /* if this text takes the tehandle over the 32K limit, then we have to throw some away at the top first. */ teLen = (**(**gH).TEH).teLength; if ((teLen + len) > 32767) { TooMuchText(); TESetSelect(0,len + kHeadRoom,(**gH).TEH); TEDelete((**gH).TEH); } TESetSelect(32767,32767,(**gH).TEH); TEInsert(*(Handle)(theInfo->eventParams[1]),len,(**gH).TEH); AdjustText(); ShowSelection(); InvalRect(&gWindow->portRect); return; } if (EqualString(s,"\pSELTEXT",FALSE,FALSE)) { strcpy(s,*(Handle)(theInfo->eventParams[1])); if (NumHCItems(s) == 2) { GetHCItem(s,1,num); if (!IsNumber(num,&start)) return; GetHCItem(s,2,num); if (!IsNumber(num,&end)) return; TEDeactivate((**gH).TEH); TESetSelect(start,end,(**gH).TEH); ShowSelection(); } } if (EqualString(s,"\pLOCKTEXT",FALSE,FALSE)) { strcpy(s,*(Handle)(theInfo->eventParams[1])); CtoPstr(s); if (EqualString(s,"\pTRUE",FALSE,FALSE)) { (**gH).pLockText = TRUE; ActivateEdit(FALSE); } else if (EqualString(s,"\pFALSE",FALSE,FALSE)) (**gH).pLockText = FALSE; else gParamPtr->passFlag = TRUE; return; } if (EqualString(s,"\pTEXTFONT",FALSE,FALSE)) { strcpy(s,*(Handle)(theInfo->eventParams[1])); if (strlen((char*)s) > 0) { CtoPstr(s); GetFNum(s,&i); (**gH).pFont = i; TextFont(i); GetFontInfo(&fi); (**(**gH).TEH).lineHeight = fi.ascent + fi.descent + fi.leading; (**(**gH).TEH).fontAscent = fi.ascent; (**(**gH).TEH).txFont = i; TECalText((**gH).TEH); InvalRect(&gWindow->portRect); } } if (EqualString(s,"\pTEXTSIZE",FALSE,FALSE)) { strcpy(s,*(Handle)(theInfo->eventParams[1])); if (strlen((char*)s) > 0) { if (IsNumber(s,&n)) { (**gH).pTextSize = (int)n; TextSize((**gH).pTextSize); GetFontInfo(&fi); (**(**gH).TEH).lineHeight = fi.ascent + fi.descent + fi.leading; (**(**gH).TEH).fontAscent = fi.ascent; (**(**gH).TEH).txSize = n; TECalText((**gH).TEH); InvalRect(&gWindow->portRect); } } }}/* Hilite the range of lines specified. */void HiliteLines(long start,long finish){ int p1,p2; p1 = (**(**gH).TEH).lineStarts[start-1]; if ((finish == -1L) || (finish < start)) p2 = (**(**gH).TEH).lineStarts[start]; else p2 = (**(**gH).TEH).lineStarts[finish]; TESetSelect(p1,p2,(**gH).TEH); ShowSelection(); ActivateEdit(true);}/* Hilite the range of characters specified. */void HiliteChars(long start,long finish){ int p1,p2; p1 = start-1; if ((finish == -1L) || (finish < start)) p2 = start; else p2 = finish; TESetSelect(p1,p2,(**gH).TEH); ShowSelection(); ActivateEdit(true);}/* ================== Window Static Global Data ============= *//* Handle load and store of static global block that hangs off the XWindow refcon. After a create of load, we lock the handle so that the rest of the XCMD can directly use the fields of the record stored at the handle. *//* Create a heap block to store our static globals in. */void CreateStaticGlobals(void){ long len; /* create the handle */ len = sizeof(StaticGlobals); gH = NULL; gH = (StaticGlobalsH)NewHandle(len); if (gH != NULL) HLock((Handle)gH);}/* Load the static globals and lock them down for our use. */ void LoadStaticGlobals(void){ if (gWindow==NULL) return; /* follows a close operation */ gH = (StaticGlobalsH)((WindowPeek)gWindow)->refCon; if (gH==NULL) { DebugStr("\pnull globals handle"); /* need better report */ return; } HLock((Handle)gH); }</span></text>
</content>
<name>EditWindow</name>
<script>on openCardhide cd fld "save"pass openCardend openCardon closeCardglobal gEditWindow,gEditWindow2if there is a window id gEditWindow thenclose window id gEditWindowend ifif there is a window id gEditWindow2 thenclose window id gEditWindow2end ifhide msgpass closeCardend closeCardfunction CloseEditWindow changedif not changed thenhide cd btn "scan"exit CloseEditWindowend ifanswer "Save Changes before closing?" with "Cancel","No","Yes"if it is "No" thenreturn trueelse if it is "Cancel" thenreturn falseend ifglobal gEditWindowget the text of window id gEditWindowshow cd fld "save"put it into cd fld "save"return TRUEend CloseEditWindowon CommandClickInEditWindow windowID,textput "You clicked on ""e& text"e&" in window id "&windowID&"." into msgend CommandClickInEditWindow</script>
</card>
card_9112.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<script>on mouseUpget modaldialog(serialhandler,empty,cardCenter)if it is not "cancel" thenset the visible of button "put" to trueset the visible of button "get" to trueset the visible of button "putnulls" to trueset the visible of button "getnulls" to truehide meend ifend mouseUp</script>
</part>
<part>
<id>3</id>
<type>field</type>
<visible> <true /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>266</left>
<top>303</top>
<right>413</right>
<bottom>334</bottom>
</rect>
<style>shadow</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Chicago</font>
<textSize>10</textSize>
<textStyle>plain</textStyle>
<textHeight>13</textHeight>
<name></name>
<script></script>
</part>
<part>
<id>4</id>
<type>button</type>
<visible> <false /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>85</left>
<top>301</top>
<right>120</right>
<bottom>319</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Put</name>
<script>on mouseUp-- You may have to change the parameter list to suit your configuration-- NOTE: This button is a self contained operation of open, put,close.-- You DO NOT have to open and close every time you get or put.-- Just open once and start once, like when you open and close-- your stack.put "Warning: This demo assumes a serial port setting of: " into xput "A,2400,8,none,1,XON/XOFF. Edit the script of the " after xput the short name of me after xput " button to change the settings." after xanswer x with "Cancel","OK"if it is "Cancel" then exit mouseUpset the cursor to watchget SerialHandler("open","A",2400,8,none,1,"XON/XOFF")if it is not empty thenput "Error: "&&it&&" (See script of 'put' button)"end ifput the number of lines in the script of me into nlrepeat with i = 1 to nlget line i of the script of meget Serialhandler("put","A",it&return&numToChar(10))end repeatif it is not empty thenput "Error: "&&itend ifget Serialhandler("close","A")end mouseUp</script>
</part>
<part>
<id>5</id>
<type>button</type>
<visible> <false /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>85</left>
<top>322</top>
<right>121</right>
<bottom>340</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Get</name>
<script>on mouseUp-- You may have to change the parameter list to suit your configuration-- NOTE: This button is a self contained operation of open, get,close.-- You DO NOT have to open and close every time you get or put.-- Just open once and start once, like when you open and close-- your stack.put "Warning: This demo assumes a serial port setting of: " into xput "A,2400,8,none,1,XON/XOFF. Edit the script of the " after xput the short name of me after xput " button to change the settings." after xanswer x with "Cancel","OK"if it is "Cancel" then exit mouseUpset the hilite of me to trueset the cursor to watchget SerialHandler("open","A",2400,8,none,1,"XON/XOFF")set the visible of card field "got" to trueput empty into card field "got"put "Click the mouse when done."put "Characters received on the serial port will appear below:"¬&return&return into card field "got"repeat while the mouse is upget SerialHandler("get","A",60)put it after card field "got"end repeatget SerialHandler("close","A")set the visible of card field "got" to falseset the hilite of me to falseput empty into msghide msgend mouseUp</script>
</part>
<part>
<id>6</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>18</left>
<top>40</top>
<right>494</right>
<bottom>288</bottom>
</rect>
<style>scrolling</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Geneva</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<textHeight>16</textHeight>
<name>got</name>
<script></script>
</part>
<part>
<id>7</id>
<type>button</type>
<visible> <false /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>139</left>
<top>301</top>
<right>209</right>
<bottom>319</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>PutNulls</name>
<script>on mouseUp-- You may have to change the parameter list to suit your configuration-- NOTE: This button is a self contained operation of open, put,close.-- You DO NOT have to open and close every time you get or put.-- Just open once and start once, like when you open and close-- your stack.put "Warning: This demo assumes a serial port setting of: " into xput "A,2400,8,none,1,XON/XOFF. Edit the script of the " after xput the short name of me after xput " button to change the settings." after xanswer x with "Cancel","OK"if it is "Cancel" then exit mouseUpset the cursor to watchask "Put how many nulls?"if it is empty then exit mouseUpget SerialHandler("open","A",2400,8,none,1,"XON/XOFF")if it is not empty thenput "Error: "&&it&&" (See script of 'put' button)"end ifget Serialhandler("putnulls","A",it)get Serialhandler("put","A","<- nulls precede this."&return&numToChar(10))if it is not empty thenput "Error: "&&itend ifget Serialhandler("close","A")end mouseUp</script>
</part>
<part>
<id>8</id>
<type>button</type>
<visible> <false /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>139</left>
<top>322</top>
<right>209</right>
<bottom>340</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>GetNulls</name>
<script>on mouseUp-- You may have to change the parameter list to suit your configuration-- NOTE: This button is a self contained operation of open, get,close.-- You DO NOT have to open and close every time you get or put.-- Just open once and start once, like when you open and close-- your stack.put "Warning: This demo assumes a serial port setting of: " into xput "A,2400,8,none,1,XON/XOFF. Edit the script of the " after xput the short name of me after xput " button to change the settings." after xanswer x with "Cancel","OK"if it is "Cancel" then exit mouseUpset the hilite of me to trueset the cursor to watchget SerialHandler("open","A",2400,8,none,1,"XON/XOFF")set the visible of card field "got" to trueput empty into card field "got"put "Click the mouse when done."put "Characters received on the serial port will appear below:"¬&return&return into card field "got"repeat while the mouse is upget SerialHandler("getnulls","A",60)put it after card field "got"end repeatget SerialHandler("close","A")set the visible of card field "got" to falseset the hilite of me to falseput empty into msghide msgend mouseUp</script>
</part>
<content>
<layer>background</layer>
<id>16</id>
<text><span class="style1">erialHandler XFCN version 1.4</span><span class="style2">Roger BrownSerialhandler is a HyperCard XFCN that opens access to the Macintosh serial ports. Several functions are available through the one handler. Each is specified by an opcode in the first parameter. Successive parameters and the return value depend on the opcode.OPCODE INPUT DEFAULT OUTPUT======= ===== ======= ======="open " port (A,B) A = modem error messages baud (300-57600) 9600 if any, or the value of a handle data bits (5-8) 8 to the input buffer if parity (odd,even,none) none one larger than 64 stop bits (1,1.5,2) 1 bytes is requested flow control (XON/XOFF,CTS) XON/XOFF input buffer size 64 bytes "close" port (A,B) A = modem none input buffer (optional)"put" port (A,B) A = modem error messages source of characters none"get" port (A,B) A = modem error messages if any, timeout (ticks) 30 (1/2 sec) or characters received"putnulls" port (A,B) A = modem error messages count (how many to put)"getnulls" port (A,B) A = modem error messages or characters recieved formatted as one line per character, a blank line indicating a null. A received return character is indicated by a line consisting of '\r'. "version" XCMD version number "break" port (A,B) ticks (length of the break in ticks = 1/60 sec or 16.67 ms) INVOKING SerialHandler get SerialHandler(task,port,...) where task is the opcode: open,close,put,or get port is the port to use ... other parameters as in the table aboveEXAMPLES 1. Opening with no parameters beyond the opcode will give you the defaults. ex. get SerialHandler("open") 2. If you want an input buffer larger than 64 bytes then you must declare a global variable to be used for only this purpose. Assign the return result of the open call to this global. The value of the global is the memory location of the large buffer. It will be locked until you close the serial port. It is very important that you do not change the value of this global and that you pass it back to SerialHandler in the " close" call before opening SerialHandler again. If you are using both ports, keep a separate buffer global for each. ex. On OpenPort global serialBufferA -- declare the global here put SerialHandler(open,A,4800,8,none,1,CTS,1024) into serialBufferA -- open the port and assign a 1024 byte buffer which is remembered in -- global serialBufferA end OpenPort on ClosePort global serialBufferA get SerialHandler("close","A",serialBufferA) -- close port, dispose the input -- buffer end closePort 3. When getting characters from the port, the timeout parameter is the minimum time that SerialHandler will wait for input. If there are still characters to be read at the end of the timeout period, SerialHandler will keep on reading until there are no more to be read. ex. put SerialHandler("get","A",60) into charsRecieved 4. get Serialhandler("put","A",the script of this stack) will send the text of the script out serial port A, assuming it has been opened.REVISION HISTORY1.0a0 7/5/88 alpha release 1.0a1 7/11/88 mistake in GetSerialChars - 1st call to SetGetBuff had AinRefNum instead of port as input1.0a2 12/9/88 Call to ResultIs with an empty string was leaving orphan handles in the heap. Also, changed for compilation under LSC 3.0.1.1a0 first non-public domain source version1.1a7 9/1/89 Fixed bug in OpenSerial default handling that could cause random bus errors.1.1a9 Fixed bug in the deallocation of memory if a buffer greater than 64K is used. Memory blocks were orphaned if there were multiple opens and closes in a single HyperCard session.1.1a10 Check first parameter for emptiness.1.1a11 11/21/90 Added "PutNulls" command to put a stream of null characters. Nulls must be sent separately from all other characters, with a count parameter to indicate how many to send.1.1a13 2/5/91 Added "GetNulls" command to receive null characters. Received characters are returned in a format of one character per line. A blank line indicates a null. Also added "version" command to get the version number. And changed this documentation to show that the maximum baud rate is 57600 rather than 9600.1.2d7 10/19/92 No new features, but some bugs fixed.1.2 2/5/93 Added VERSION command.1.3 3/16/93 Fixed erroneous error message on close when no buffer was set in open. Added BREAK (ticks) command.1.4 3/31/93 GetNulls returns "\r" if it receives a return character from the serial device.</span></text>
</content>
<content>
<layer>card</layer>
<id>3</id>
<text><span class="style2">he source is not in the public domain, sorry.</span><span class="style4"></span></text>
</content>
<content>
<layer>background</layer>
<id>44</id>
<text>HC1,HC2,SC</text>
</content>
<content>
<layer>background</layer>
<id>45</id>
<text>Revised</text>
</content>
<content>
<layer>card</layer>
<id>6</id>
<text>Characters received on the serial port will appear below:</text>
</content>
<name>SerialHandler</name>
<script>on opencardset the visible of button "put" to falseset the visible of button "get" to falseset the visible of button "putnulls" to falseset the visible of button "getnulls" to falseshow btn "serialhandler"pass opencardend opencardon closecardset the visible of button "put" to falseset the visible of button "get" to falseset the visible of button "putnulls" to falseset the visible of button "getnulls" to falseshow btn "serialhandler"pass closecardend closecard</script>
</card>
card_6629.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<script>on mouseUpDoSearch-- the handler for the DoSearch message is in the script of-- this stackend mouseUp</script>
</part>
<part>
<id>12</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>278</left>
<top>311</top>
<right>417</right>
<bottom>333</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Show Pascal Source</name>
<script>on mouseUpset the visible of field "source" to not the visible of field "source"if the visible of field "source" is true thenset the name of me to "Hide Pascal Source"else set the name of me to "Show Pascal Source"end mouseUp</script>
</part>
<content>
<layer>background</layer>
<id>16</id>
<text><span class="style1">ODALDIALOG XFCN version 1.2</span><span class="style2">Kevin CalhounModalDialog displays a dialog box created by any resource generator or editor, such as ResEdit. It permits the user to interact with the dialog in the standard Macintosh fashion and, once the user dismisses the dialog, returns information about the contents of all the editable text items and the state of all the check boxes and radio buttons at the time the dialog was dismissed.INVOKING MODALDIALOGget ModalDialog("DLOGName",<containerName>,<dialogPositioning>,<noCancel>,<noWordWrap>,<selectedItem>)returns if the user presses the default button: a multi-lined expression, explained below, describing the contents of the dialog box if the user presses the cancel button: "Cancel" if an error occurs: "Error " followed by an error codeWHAT YOU PASS TO MODALDIALOGYou tell ModalDialog which dialog to display by passing the name of its DLOG resource in the first parameter. For example, ModalDialog("ask") brings up HyperCard's ask dialog. You should enclose this name in quotation marks.The rest of the parameters are optional.The second parameter, containerName, is the name of a HyperTalk container. Before calling ModalDialog, you can store a multi-lined expression in this container that will determine the following properties of the dialog: the text of text items, the initial state of check boxes and radio buttons, the grouping of radio buttons, and the default and cancel buttons. The container should include one line for each dialog item in the DITL resource--ModalDialog matches each dialog item with the corresponding line in the container. If there is no second parameter, or if it is empty, then the dialog will appear in the default state: the text items will contain the text specified by the DITL, check boxes and radio buttons will be turned off, all radio buttons will be grouped together, the default button will be the first button in the DITL, and the cancel button will be the second button in the DITL. The next few paragraphs explain how to override this default behavior.If the dialog item is a button control, ModalDialog looks in its corresponding line in containerName for two items: defaultOrCancel,NameIf defaultOrCancel is "Default", the button becomes the default button (the one that's pushed when the user presses the return or enter key) and the familiar bold outline will be drawn around it. If defaultOrCancel is "Cancel", the button becomes the cancel button (the one that's pushed when the user presses the escape key, command-period, or command-Q). If more than one button is designated the default button, the last of these in the list becomes the actual default button. The same rule applies for multiple buttons designated the cancel button. If Name is not empty, then the title of the button will be set to it.If the dialog item is a check box, ModalDialog looks in its corresponding line in containerName for two items: onOrOff,NameIf onOrOff is "On", the check box will be checked when it first appears. If Name is not empty, the title of the check box will be set to it.If the dialog item is a radio button, ModalDialog looks in its corresponding line in containerName for three items: onOrOff,group,NameIf onOrOff is "On", the radio button will be on when it first appears. Group is a number that tells ModalDialog which radio buttons should be turned off when the user turns the radio button on. When the user clicks a radio button, ModalDialog does nothing if the radio button is already on; if it's off, every other radio button with the same group number is turned off before it's turned on. If group is empty, the radio button is assigned to group number 0. (Note: ModalDialog doesn't check whether you turn more than one radio button on within the same group. If you do this, the radio buttons in that group will not behave normally.) If Name is not empty, the title of the radio button will be set to it.If the dialog item is an editable or static text item, ModalDialog will set the text of the dialog item to the line in containerName that corresponds to it, unless that line is empty.If the dialog item is an icon item, a picture item, a user item, or a control defined by a resource template in a resource file, ModalDialog ignores the line in containerName that corresponds to it.The third parameter, dialogPositioning, tells ModalDialog how to position the dialog on the screen, as follows. dialogPositioning effect--------------------- ------------------------------------------------------------------------- "cardOffset" coordinates in DLOG resource are treated as local to the card"cardCenter" the dialog is centered over the card window"screenCenter" the dialog is centered on the main screenIn addition, each of these options may be preceded by an "h" or a "v", with the following effects: "h" tells ModalDialog to alter only the horizontal positioning of the dialog, while "v" tells it to alter only the vertical positioning. For example, "hScreenCenter" will cause the dialog to be centered horizontally on the screen while retaining the vertical positioning specified in the DLOG resource. If there is no third parameter, or if it is something other than these options, the coordinates ModalDialog finds in the DLOG resource are treated as global coordinates and become the dialog's bounding rectangle. (Note: for compatibility with earlier versions, TRUE means the same thing as "cardOffset".)The fourth parameter, noCancel, tells ModalDialog whether or not there is a cancel item. If noCancel is TRUE, the user cannot dismiss the dialog by pressing command-period, command-Q, or the escape key, or by pressing any button other than the default item. If noCancel is not present, or if it is anything other than TRUE, then the cancel item is determined by the methods described above and the dialog can be cancelled.The fifth parameter, noWordWrap, tells ModalDialog whether or not you want automatic word wrapping in edit text items. If it is TRUE, there will be no word wrap. If it is absent or anything other than TRUE, the words will wrap.The sixth parameter, selectedItem, specifies the number of the editable text item to be selected when the dialog appears. If this parameter is absent or does not contain the number of an editable text item, the first edit item in the list will be selected.WHAT MODALDIALOG RETURNSIf the user dismisses the dialog by clicking the default item or by pressing return or enter, ModalDialog returns a multi-line expression, one line per item in the dialog item list, describing what the dialog contained when it was dismissed.If the item is a check box or a radio button, the line corresponding to it will contain "off" if the button was off and "on" if the button was on.If the item is an edit text item, the line corresponding to it will contain the text of the item.If the item is any other type of dialog item, the line corresponding to it will be empty.If the user dismisses the dialog by clicking the cancel item or by pressing command-period, command-Q, or the escape key, then ModalDialog returns "Cancel".REVISION HISTORYMarch 15, 1989 -- 1.0 release.March 31, 1989 -- 1.0.1. Sped up scanning of input container. Container name should no longer be quoted. Default group for radio buttons is now 0, not 1.April 3, 1989 -- 1.0.2. Added pre-flight check for presence of DITL resource. Added more options for dialog positioning.June 25, 1989 -- 1.0.3. If user copies a selection from an edit text item in the dialog, the desk scrap will contain that text after the dialog is dismissed.May 11, 1990 -- 1.1. Line in input container for editable text items now contains only the text, not a select boolean (to allow commas in the text). Initially selected item is specified with new selectedItem parameter.March 29, 1993 -- 1.2 Imports the scrap so you can paste into the text item when first opened.</span></text>
</content>
<content>
<layer>background</layer>
<id>36</id>
<text>UNIT ModalDialogUnit;{ ModalDialog 1.2 XCMD ©1989 by the Trustees of Dartmouth College }{ Written by Kevin Calhoun }{ Modified by Susan Tenney and Roger Brown }{ This source compatible with MPW Pascal 3.0 }(*Pascal ModalDialog.pLink -m ENTRYPOINT ∂ -o "YourFile" ∂ -rt XFCN=13013 ∂ -sg ModalDialog ∂ -sn Main=ModalDialog ∂ ModalDialog.p.o ∂ "{Libraries}"interface.o ∂ "{PLibraries}"Paslib.o ∂ "{Libraries}"HyperXLib.o*){$R-}INTERFACE USES Types, Memory, Resources, Dialogs, Scrap, ToolUtils, OSUtils, Packages, Errors, HyperXCmd; PROCEDURE Entrypoint (paramPtr : XCmdPtr);IMPLEMENTATION CONST btnOn = 1; TYPE GlobalsHandle = ^GlobalsPtr; GlobalsPtr = ^GlobalsRecord; GlobalsRecord = RECORD dlogItems : INTEGER; wasDown : BOOLEAN; alteredScrap : BOOLEAN; defaultItem : INTEGER; cancelItem : INTEGER; selectedItem : INTEGER; editTextRgn : RgnHandle; arrowCursor, iBeamCurs : Cursor; END; WordHandle = ^WordPtr; WordPtr = ^INTEGER; PROCEDURE DoModalDlog (paramPtr : XCmdPtr); FORWARD; PROCEDURE Entrypoint (paramPtr: XCMDPtr); BEGIN DoModalDlog(paramPtr); END; FUNCTION GetScreenBitsBounds: Rect; TYPE LongwordPtr = ^LONGINT; BitMapPtr = ^BitMap; CONST screenBitsOffset = -122; CurrentA5 = $904; VAR screenBitsPtr : BitMapPtr; myLongwordPtr : LongwordPtr; BEGIN myLongwordPtr := LongwordPtr(CurrentA5); myLongwordPtr := LongwordPtr(myLongwordPtr^); screenBitsPtr := BitMapPtr(myLongwordPtr^ + screenBitsOffset); GetScreenBitsBounds := screenBitsPtr^.bounds; END; FUNCTION GetArrowCursor : Cursor; TYPE LongwordPtr = ^LONGINT; CONST arrowOffset = -108; CurrentA5 = $904; VAR arrowPtr : CursPtr; myLongwordPtr : LongwordPtr; BEGIN myLongwordPtr := LongwordPtr(CurrentA5); myLongwordPtr := LongwordPtr(myLongwordPtr^); arrowPtr := CursPtr(myLongwordPtr^ + arrowOffset); GetArrowCursor := arrowPtr^; END; PROCEDURE DrawBoxAroundDefault (theWindow : WindowPtr; itemNo : INTEGER); VAR itemType : integer; itemHdl : Handle; itemBox : rect; item : INTEGER; g : GlobalsHandle; ps : PenState; savePort : GrafPtr; BEGIN { If you steal this routine, get rid of the next three lines } { and figure out what the default item is some other way. } { Unless, of course, you use a handle to "globals" in the refCon } { field, just as I do. } g := GlobalsHandle(GetWRefCon(theWindow)); item := g^^.defaultItem; GetDItem(theWindow, item, itemType, itemHdl, itemBox); IF itemType = ctrlItem + btnCtrl THEN BEGIN GetPort(savePort); SetPort(theWindow); GetPenState(ps); PenSize(3, 3); InsetRect(itemBox, -4, -4); FrameRoundRect(itemBox, 16, 16); SetPenState(ps); SetPort(savePort); END; END; FUNCTION AddUserItem (d: DialogPtr; default: INTEGER) : OSErr; TYPE DItemPtr = ^dialogItem; DItemHndl = ^dItemPtr; DialogItem = RECORD placeholder : handle; displayRect : Rect; typeAndDataLength : INTEGER; END; VAR theUserItem : DItemHndl; itemType : INTEGER; itemHdl : Handle; itemBox : Rect; theItems : Handle; err : OSErr; BEGIN err := noErr; GetDItem(d, default, itemType, itemHdl, itemBox); IF itemType = ctrlItem + btnCtrl THEN BEGIN InsetRect(itemBox, -4, -4); theUserItem := DItemHndl(NewHandle(SIZEOF(DialogItem))); err := MemError; IF (theUserItem <> NIL) AND (err = noErr) THEN BEGIN MoveHHi(Handle(theUserItem)); HLock(Handle(theUserItem)); WITH theUserItem^^ DO BEGIN placeholder := Handle(@DrawBoxAroundDefault); displayRect := itemBox; typeAndDataLength := userItem * 256 + 0; END; theItems := DialogPeek(d)^.Items; err := HandAndHand(Handle(theUserItem), theItems); WordHandle(theItems)^^ := WordHandle(theItems)^^ + 1; DisposHandle(Handle(theUserItem)); END; END; AddUserItem := err; END; FUNCTION PtrToString (p: Ptr; size: byte): Str255; TYPE StrArray = PACKED ARRAY[0..255] of char; VAR s: Str255; BEGIN StrArray(s)[0] := CHR(size); BlockMove(p, Ptr(ORD4(@s) + 1), size); PtrToString := s; END; FUNCTION GetNextLine(paramPtr: XCMDPtr; var scanPtr: Ptr; var line: Str255) : BOOLEAN; VAR tempPtr : Ptr; temp : BOOLEAN; stringLength : LONGINT; BEGIN tempPtr := scanPtr; ScanToReturn(paramPtr, scanPtr); stringLength := ORD4(scanPtr)-ORD4(tempPtr); line := PtrToString(tempPtr, stringLength); GetNextLine := (scanPtr^ = 0); { advance our pointer beyond the CR, for the next time we're called } scanPtr := Ptr(ORD4(scanPtr)+1); END; FUNCTION GetNextItem(sPtr: StringPtr; var index: INTEGER; var item: Str255) : BOOLEAN; VAR start: INTEGER; sLength: INTEGER; BEGIN sLength := LENGTH(sPtr^); start := index; WHILE (sPtr^[index] <> ',') AND (index < sLength) DO index := index+1; IF index >= sLength THEN BEGIN GetNextItem := TRUE; IF sPtr^[sLength] = ',' THEN index:=index-1; item := COPY(sPtr^, start, (index-start+1)); index := sLength+1; END ELSE BEGIN GetNextItem := FALSE; item := COPY(sPtr^, start, (index-start)); index := index+1; END; END; PROCEDURE SetButtonItem(item: INTEGER; c: ControlHandle; desc: Str255); VAR lastItem : BOOLEAN; itemStr: Str255; g: GlobalsHandle; index: INTEGER; BEGIN index := 1; lastItem := GetNextItem(@desc, index, itemStr); g := GlobalsHandle(GetWRefCon(c^^.contrlOwner)); IF IUEqualString(itemStr, 'Default') = 0 THEN g^^.defaultItem := item ELSE IF IUEqualString(itemStr, 'Cancel') = 0 THEN g^^.cancelItem := item; IF NOT lastItem THEN BEGIN lastItem := GetNextItem(@desc, index, itemStr); IF LENGTH(itemStr) > 0 THEN SetCTitle(c, itemStr); END; END; PROCEDURE SetCheckBox(item: INTEGER; c: ControlHandle; desc: Str255); VAR lastItem: BOOLEAN; itemStr: Str255; index: INTEGER; BEGIN index := 1; lastItem := GetNextItem(@desc, index, itemStr); IF IUEqualString(itemStr, 'On') = 0 THEN SetCtlValue(c, btnOn); IF NOT lastItem THEN BEGIN lastItem := GetNextItem(@desc, index, itemStr); IF LENGTH(itemStr) > 0 THEN SetCTitle(c, itemStr); END; END; PROCEDURE SetRadioButton(paramPtr: XCMDPtr; item: INTEGER; c: ControlHandle; desc: Str255); VAR lastItem : BOOLEAN; itemStr: Str255; group: INTEGER; index: INTEGER; BEGIN index := 1; lastItem := GetNextItem(@desc, index, itemStr); IF IUEqualString(itemStr, 'On') = 0 THEN SetCtlValue(c, btnOn); IF NOT lastItem THEN BEGIN lastItem := GetNextItem(@desc, index, itemStr); IF LENGTH(itemStr) > 0 THEN BEGIN group := StrToNum(paramPtr, itemStr); SetCRefCon(c, group); END; IF NOT lastItem THEN BEGIN lastItem := GetNextItem(@desc, index, itemStr); IF LENGTH(itemStr) > 0 THEN SetCTitle(c, itemStr); END; END; END; FUNCTION GetSelectedItem( paramPtr: XCMDPtr ; def : INTEGER ; dlogPtr : DialogPtr ; numItems : INTEGER ) : INTEGER ; VAR sel : INTEGER ; selStr : Str255 ; iType : INTEGER ; iHandle : Handle ; box : Rect ; BEGIN sel := def ; IF paramPtr^.paramCount > 5 THEN BEGIN ZeroToPas( paramPtr, paramPtr^.params[6]^, selStr ) ; sel := StrToNum( paramPtr, selStr ) ; IF (paramPtr^.result <> 0) OR (sel < 1) OR (sel > numItems) THEN sel := def ELSE BEGIN GetDItem( dlogPtr, sel, iType, iHandle, box ) ; IF iType <> editText THEN sel := def ; END ; END ; GetSelectedItem := sel ; END ; PROCEDURE SetDialogItems(paramPtr: XCMDPtr; d: DialogPtr; dlogItems: INTEGER; inContainer: Handle); VAR hs: SignedByte; scanPtr: Ptr; i : INTEGER; str : Str255; lastLine : BOOLEAN; itemType : integer; itemHdl : Handle; itemBox : rect; BEGIN hs := HGetState(inContainer); HLock(inContainer); scanPtr := inContainer^; FOR i := 1 to dlogItems DO BEGIN GetDItem(d, i, itemType, itemHdl, itemBox); lastLine := GetNextLine(paramPtr, scanPtr, str); CASE itemType MOD itemDisable OF ctrlItem + btnCtrl: SetButtonItem(i, ControlHandle(itemHdl), str); ctrlItem + chkCtrl: SetCheckBox(i, ControlHandle(itemHdl), str); ctrlItem + radCtrl: SetRadioButton(paramPtr, i, ControlHandle(itemHdl), str); statText, editText: IF LENGTH(str) > 0 THEN SetIText(itemHdl, str); END; { case itemType MOD itemDisable } IF lastLine then Leave; END; { for i := 1 to dlogItems } HSetState(inContainer, hs); END; FUNCTION ItemCount (theDialogPtr : DialogPtr) : integer; BEGIN ItemCount := WordHandle(DialogPeek(theDialogPtr)^.items)^^ + 1; END; FUNCTION GetLocOfCardWindow (cardWindow : WindowPtr) : Point; VAR savePort : GrafPtr; pt: Point; BEGIN GetPort(savePort); SetPort(cardWindow); WITH cardWindow^.portRect DO SetPt(pt,left,top); LocalToGlobal(pt); SetPort(savePort); GetLocOfCardWindow := pt; END; PROCEDURE MoveDialogRelativeToWindow (cardWindow: WindowPtr; doH, doV: BOOLEAN; theDialogTHndl : DialogTHndl); VAR tempRect : Rect; cardLoc : Point; BEGIN tempRect := theDialogTHndl^^.boundsRect; cardLoc := GetLocOfCardWindow(cardWindow); WITH cardLoc DO BEGIN {offset our DLOG rect according to loc of card window } IF NOT doH THEN h := 0; IF NOT doV THEN v := 0; OffSetRect(tempRect, h, v); END; theDialogTHndl^^.boundsRect := tempRect; { set DLOG boundsRect} END; PROCEDURE CenterRect(VAR r: Rect; inRect: Rect; doH, doV: BOOLEAN); VAR hSize, vSize: INTEGER; hCoord, vCoord: INTEGER; BEGIN WITH r DO BEGIN hCoord := left; vCoord := top; hSize := right-left; vSize := bottom-top; END; WITH inRect DO BEGIN IF doH THEN hCoord := (right-left - hSize) DIV 2 + left; IF doV THEN vCoord := (bottom-top - vSize) DIV 2 + top; END; SetRect(r, hCoord, vCoord, hCoord+hSize, vCoord+vSize); END; PROCEDURE CenterDialogOverWindow(cardWindow: WindowPtr; doH, doV: BOOLEAN; theDialogTHndl: DialogTHndl); VAR cardLoc : Point; windowRect: Rect; dlogRect: Rect; BEGIN cardLoc := GetLocOfCardWindow(cardWindow); windowRect := cardWindow^.portRect; WITH windowRect DO OffsetRect(windowRect, -left, -top); WITH cardLoc DO OffsetRect(windowRect, h, v); dlogRect := theDialogTHndl^^.boundsRect; CenterRect(dlogRect, windowRect, doH, doV); theDialogTHndl^^.boundsRect := dlogRect; END; PROCEDURE CenterDialogOverScreen(doH, doV: BOOLEAN; theDialogTHndl: DialogTHndl); VAR screenRect: Rect; dlogRect: Rect; BEGIN dlogRect := theDialogTHndl^^.boundsRect; screenRect := GetScreenBitsBounds; CenterRect(dlogRect, screenRect, doH, doV); theDialogTHndl^^.boundsRect := dlogRect; END; FUNCTION SetUpGlobals (theDialog : DialogPtr) : OSErr; LABEL 99; VAR err : OSErr; numItems, i : INTEGER; g : GlobalsHandle; tempRgn : RgnHandle; itemType : INTEGER; ItemHdl : Handle; itemBox : rect; iBeam : CursHandle; gotDefault, gotCancel, gotSelectedItem: BOOLEAN; BEGIN err := noErr; g := GlobalsHandle(NewHandle(SizeOf(GlobalsRecord))); err := MemError; IF (err <> noErr) or (g = NIL) then GOTO 99; numItems := ItemCount(theDialog); WITH g^^ DO BEGIN dlogItems := numItems; wasDown := FALSE; alteredScrap := FALSE; END; gotDefault := FALSE; gotCancel := FALSE; gotSelectedItem := FALSE; tempRgn := NewRgn; OpenRgn; FOR i := 1 TO numItems DO BEGIN GetDItem(theDialog, i, itemType, itemHdl, itemBox); CASE itemType OF editText, editText+itemDisable: BEGIN FrameRect(itemBox); IF not gotSelectedItem THEN BEGIN g^^.selectedItem := i; gotSelectedItem := TRUE; END; END; ctrlItem + btnCtrl: IF not gotDefault THEN BEGIN g^^.defaultItem := i; gotDefault := TRUE; END ELSE IF not gotCancel THEN BEGIN g^^.cancelItem := i; gotCancel := TRUE; END; END; END; CloseRgn(tempRgn); err := MemError; IF err <> noErr THEN BEGIN DisposHandle(Handle(g)); GOTO 99; END; IF not gotDefault THEN g^^.defaultItem := OK; IF not gotCancel THEN g^^.cancelItem := Cancel; IF not gotSelectedItem THEN g^^.selectedItem := 0; g^^.editTextRgn := tempRgn; iBeam := GetCursor(iBeamCursor); g^^.iBeamCurs := iBeam^^; g^^.arrowCursor := GetArrowCursor; SetWRefCon(theDialog,LONGINT(g)); 99: SetUpGlobals := err; END; PROCEDURE DisposeGlobals (theDialog : DialogPtr); VAR g : GlobalsHandle; rgn : RgnHandle; BEGIN g := GlobalsHandle(GetWRefCon(theDialog)); rgn := g^^.editTextRgn; DisposeRgn(rgn); DisposHandle(Handle(g)); END; FUNCTION TheFilter (theDialog : DialogPtr; VAR theEvent : EventRecord; VAR itemHit : integer) : boolean; VAR mouseLoc : Point; theItem : INTEGER; numItems : INTEGER; g : GlobalsHandle; curs : Cursor; theChar : INTEGER; FUNCTION SelectionNotEmpty(dlg: DialogPtr): BOOLEAN; VAR te: TEHandle; BEGIN SelectionNotEmpty := FALSE; IF DialogPeek(dlg)^.editField > -1 THEN WITH DialogPeek(dlg)^.textH^^ DO SelectionNotEmpty := selEnd > selStart; END; PROCEDURE PushButton (itemNo : INTEGER); VAR itemType : INTEGER; itemHandle : Handle; itemBox : Rect; finalTicks : longint; BEGIN GetDItem(theDialog, itemNo, itemType, itemHandle, itemBox); IF itemType = ctrlItem + btnCtrl THEN BEGIN HiliteControl(ControlHandle(itemHandle), btnOn); Delay(3, finalTicks); HiliteControl(ControlHandle(itemHandle), 0); END; END; PROCEDURE PrevEditField(dlg: DialogPtr); VAR numItems: INTEGER; theEditItem: INTEGER; itemType: INTEGER; itemHandle: Handle; itemBox: Rect; BEGIN numItems := ItemCount(dlg); IF numItems > 0 THEN BEGIN theEditItem := DialogPeek(dlg)^.editField + 1; if theEditItem > 0 then BEGIN REPEAT theEditItem := (theEditItem + numItems - 2) MOD numItems + 1; GetDItem(dlg, theEditItem, itemType, itemHandle, itemBox); UNTIL (itemType mod itemDisable = editText); SelIText(dlg, theEditItem, 0, 32767); END; END; END; BEGIN g := GlobalsHandle(GetWRefCon(theDialog)); itemHit := 0; TheFilter := false; numItems := g^^.dlogItems; IF g^^.wasDown AND NOT StillDown THEN BEGIN ObscureCursor; g^^.wasDown := false; END; mouseLoc := theEvent.where; GlobalToLocal(mouseLoc); CASE theEvent.what OF nullEvent,updateEvt : BEGIN IF PtInRgn(mouseLoc, g^^.editTextRgn) THEN curs := g^^.iBeamCurs ELSE curs := g^^.arrowCursor; SetCursor(curs); END; mouseDown : WITH g^^ DO IF PtInRgn(mouseLoc, editTextRgn) THEN wasDown := true; keyDown, autoKey : BEGIN theChar := BitAnd(theEvent.message, charCodeMask); CASE theChar OF $2E, $71, $51: { command-., -q, or -Q } BEGIN IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN BEGIN theItem := g^^.cancelItem; IF theItem > 0 THEN BEGIN PushButton(theItem); itemHit := theItem; TheFilter := TRUE; END; END; END; $78,$58: { x, X } IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN BEGIN g^^.alteredScrap := g^^.alteredScrap OR SelectionNotEmpty(theDialog); TheFilter := TRUE; DlgCut(theDialog); END; $63, $43: { c, C } IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN BEGIN g^^.alteredScrap := g^^.alteredScrap OR SelectionNotEmpty(theDialog); TheFilter := TRUE; DlgCopy(theDialog); END; $76, $56: { v, V } IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN BEGIN TheFilter := TRUE; DlgPaste(theDialog); END; $09: { tab key } IF BitAnd(theEvent.modifiers, shiftKey) <> 0 THEN BEGIN TheFilter := TRUE; PrevEditField(theDialog); END; $0D, $03: { Return or Enter } BEGIN theItem := g^^.defaultItem; IF theItem > 0 THEN BEGIN PushButton(theItem); TheFilter := true; itemHit := theItem; END; END; $1B : { escape key } BEGIN theItem := g^^.cancelItem; IF theItem > 0 THEN BEGIN PushButton(theItem); itemHit := theItem; TheFilter := TRUE; END; END; OTHERWISE ObscureCursor; END; { case theChar } END; { keyDown } END; {case theEvent.what} END; {function TheFilter} PROCEDURE DoCheckBox(c: ControlHandle); VAR controlValue : INTEGER; BEGIN controlValue := GetCtlValue(c); controlValue := (controlValue + 1) MOD 2; SetCtlValue(c, controlValue); END; PROCEDURE DoRadioButtons(d: DialogPtr; item: INTEGER; c: ControlHandle); VAR controlValue : INTEGER; group : INTEGER; numItems : INTEGER; i : INTEGER; itemType : INTEGER; itemHdl : Handle; itemBox : Rect; BEGIN controlValue := GetCtlValue(c); IF controlValue = 0 THEN BEGIN group := LoWord(GetCRefCon(c)); numItems := ItemCount(d); FOR i := 1 to numItems DO BEGIN GetDItem(d, i, itemType, itemHdl, itemBox); IF itemType = ctrlItem + radCtrl THEN BEGIN IF LoWord(GetCRefCon(ControlHandle(itemHdl))) = group THEN SetCtlValue(ControlHandle(itemHdl), 0); END; END; SetCtlValue(c, 1); END; END; FUNCTION AppendString (h: Handle; str: Str255): OSErr; BEGIN AppendString := PtrAndHand(POINTER(ORD4(@str)+1), h, LENGTH(str)); END; FUNCTION SpewOutResults(paramPtr: XCMDPtr; d: DialogPtr; numItems: INTEGER; var h: Handle): OSErr; LABEL 99; VAR err: OSErr; str: Str255; i: INTEGER; itemType: INTEGER; itemHdl: Handle; itemBox: Rect; return: String[1]; controlValue: INTEGER; zeroPtr: Ptr; PROCEDURE SetReturnValue; BEGIN SpewOutResults := err; END; PROCEDURE GetOut; BEGIN DisposHandle(h); SetReturnValue; EXIT(SpewOutResults); END; BEGIN err := noErr; return := ' '; return[1] := CHR($0D); FOR i := 1 to numItems DO BEGIN GetDItem(d, i, itemType, itemHdl, itemBox); CASE itemType MOD itemDisable OF ctrlItem + chkCtrl, ctrlItem + radCtrl: BEGIN controlValue := GetCtlValue(ControlHandle(itemHdl)); IF controlValue = btnOn THEN str := CONCAT('on', return) ELSE str := CONCAT('off', return); err := AppendString(h, str); IF err <> noErr THEN GetOut; END; editText: BEGIN GetIText(itemHdl, str); str := CONCAT(str, return); err := AppendString(h, str); IF err <> noErr THEN GetOut; END; OTHERWISE BEGIN err := AppendString(h, return); IF err <> noErr THEN GetOut; END; END; END; HLock(h); zeroPtr := POINTER(ORD4(h^)+GetHandleSize(h)-1); zeroPtr^ := 0; HUnlock(h); 99: SetReturnValue; END; PROCEDURE DoModalDlog (paramPtr : XCmdPtr); LABEL 98, 99; CONST noWrap = -1; VAR dlogName : Str255; inContainer : Handle; str : Str255;{Resource related variables} theResource, theDITL : Handle; theId, ditlID : INTEGER; theType : ResType;{Dialog related variables} numItems : INTEGER; myDialogTHndl : DialogTHndl; myDialogPtr : DialogPtr; dlogRect : Rect;{Dialog item related variables} itemType : INTEGER; ItemHdl : Handle; itemBox : rect; i, itemHit, def : INTEGER; g : GlobalsHandle; h : Handle; movedIt : BOOLEAN; hOrV : Char; doH, doV: BOOLEAN; cardWindow: WindowPtr; scrapErr: LONGINT; err : OSErr; PROCEDURE PassReturnValue (errMsg : Str255); { set theResult } BEGIN paramPtr^.returnValue := PasToZero(paramPtr, errMsg); END; BEGIN err := noErr; IF paramPtr^.paramCount = 0 THEN BEGIN PassReturnValue('ModalDialog XFCN 1.0.4, 11 May 1990, ©1989 Dartmouth College'); GOTO 99; END; GetPort(GrafPtr(cardWindow)); { get card window WindowPtr } ZeroToPas(paramPtr, paramPtr^.params[1]^, dlogName); IF LENGTH(dlogName) = 0 THEN GOTO 99; theResource := GetNamedResource('DLOG', dlogName); err := ResError; IF (theResource = NIL) OR (err <> noErr) THEN GOTO 99; IF paramPtr^.paramCount > 1 THEN inContainer := paramPtr^.params[2] ELSE inContainer := NIL; HNoPurge(theResource); GetResInfo(theResource, theID, theType, dlogName); err := ResError; IF err <> noErr THEN GOTO 99; myDialogTHndl := DialogTHndl(theResource); ditlID := myDialogTHndl^^.itemsID; theDITL := GetResource('DITL',ditlID); IF theDITL = NIL THEN BEGIN err := resNotFound; GOTO 99; END; movedIt := FALSE; myDialogTHndl^^.visible := FALSE; IF paramPtr^.paramCount > 2 THEN BEGIN dlogRect := myDialogTHndl^^.boundsRect; ZeroToPas(paramPtr, paramPtr^.params[3]^, str); hOrV := str[1]; doH := TRUE; doV := TRUE; CASE hOrV OF 'h','H': BEGIN doV := FALSE; DELETE(str, 1, 1); END; 'v','V': BEGIN doH := FALSE; DELETE(str, 1, 1); END; END; IF (IUEqualString(str, 'true')=0) OR (IUEqualString(str, 'cardOffset')=0) THEN BEGIN movedIt := TRUE; MoveDialogRelativeToWindow(cardWindow, doH, doV, myDialogTHndl); END ELSE IF IUEqualString(str, 'cardCenter') = 0 THEN BEGIN movedIt := TRUE; CenterDialogOverWindow(cardWindow, doH, doV, myDialogTHndl); END ELSE IF IUEqualString(str, 'screenCenter') = 0 THEN BEGIN movedIt := TRUE; CenterDialogOverScreen(doH, doV, myDialogTHndl); END; END; myDialogPtr := GetNewDialog(theID, NIL, POINTER(-1)); numItems := ItemCount(myDialogPtr); err := SetUpGlobals(myDialogPtr); IF err <> noErr THEN GOTO 98; IF paramPtr^.paramCount > 4 THEN BEGIN ZeroToPas(paramPtr, paramPtr^.params[5]^, str); IF StrToBool(paramPtr, str) THEN DialogPeek(myDialogPtr)^.textH^^.crOnly := noWrap; { turn off word wrap } END; IF inContainer <> NIL THEN SetDialogItems(paramPtr, myDialogPtr, numItems, inContainer); g := GlobalsHandle(GetWRefCon(myDialogPtr)); def := g^^.defaultItem; err := AddUserItem(myDialogPtr, def); IF err <> noErr THEN BEGIN DisposeGlobals(myDialogPtr); GOTO 98; END; g^^.selectedItem := GetSelectedItem( paramPtr, g^^.selectedItem, myDialogPtr, numItems ) ; IF g^^.selectedItem > 0 THEN SelIText(myDialogPtr,g^^.selectedItem,0,32767); IF paramPtr^.paramCount > 3 THEN BEGIN ZeroToPas(paramPtr, paramPtr^.params[4]^, str); IF StrToBool(paramPtr, str) THEN g^^.cancelItem := 0; END; err := TEFromScrap; {RWB 3/29/93 to allow paste from outside} ShowWindow(myDialogPtr); { make DLOG visible } BringToFront(myDialogPtr); SetPort(myDialogPtr); InitCursor; REPEAT ModalDialog(@TheFilter, itemHit); GetDItem(myDialogPtr, itemHit, itemType, itemHdl, itemBox); CASE itemType OF ctrlItem + chkCtrl: DoCheckBox(ControlHandle(itemHdl)); ctrlItem + radCtrl: DoRadioButtons(myDialogPtr, itemHit, ControlHandle(itemHdl)); END; UNTIL (itemHit = def) OR (itemHit = g^^.cancelItem); IF g^^.alteredScrap THEN BEGIN scrapErr := ZeroScrap; scrapErr := TEToScrap; END; DisposeGlobals(myDialogPtr); IF itemHit = def THEN BEGIN h := NewHandle(0); err := MemError; IF err <> noErr THEN GOTO 98; err := SpewOutResults(paramPtr, myDialogPtr, numItems, h); IF err <> noErr THEN GOTO 98; paramPtr^.returnValue := h; END ELSE PassReturnValue('Cancel'); {set rect of DLOG to original rectangle} 98: IF movedIt THEN myDialogTHndl^^.boundsRect := dlogRect; { reset DLOG boundsRect} HPurge(theResource); DisposDialog(myDialogPtr); 99: IF err <> noErr THEN BEGIN NumToStr(paramPtr, err, str); PassReturnValue(CONCAT('Error ', str)); END; END; {procedure DoModalDlog}END.</text>
<text><span class="style1">EPORTING BUGS</span><span class="style2">If you should happen to find a bug in any of our work, we'd be very grateful if you reported it to us. Tell us what version of HyperCard you were running, what version of the System Software you were running, and what kind of Macintosh you were using when the problem occurred. Please try to describe the sequence of actions you took that led up to the problem.You can reach Roger Brown at:Kiewit Computation Center, Dartmouth College,Hanover, NH 03755INTERNET: Roger.Brown@dartmouth.eduAmerica OnLine: RWBrownAppleLink: RWBROWNYou can reach Kevin Calhoun at:jkc@apple.com (INTERNET)CALHOUN.K (AppleLink)J.CALHOUN (GEnie)JKCALHOUN (America Online)71332,207 (CompuServe)</span></text>
</content>
<name>Bugs</name>
<script></script>
</card>
card_8501.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style3">istory of the Stack</span><span class="style2"></span><span class="style1">WHAT'S NEW IN THIS RELEASE (4.0.3)</span><span class="style2">ΓÇó ModalDialog accepts a paste from the clipboard when it first opens.ΓÇó Version resources are correct.ΓÇó SerialHandler GetNulls command returns "\r" for received return characters.ΓÇó EditWindow calls the closeFunction even if there are no changes.</span><span class="style1">WHAT'S NEW IN VERSION (4.0.2)</span><span class="style2">ΓÇó ReplaceChar is updated to fix a bug.ΓÇó The XCMD's menu is handled better when you switch stacks.ΓÇó ListWindow has a new zoom parameter.ΓÇó SerialHandler has one bug fixed and has a BREAK command added.</span><span class="style1">WHAT'S NEW IN VERSION (4.0.1)</span><span class="style2">ΓÇó The SerialHandler demo and ListWindow demos had a few problems that were fixed.ΓÇó Version 4.0 had two copies of SerialHandler with different ID's. One did not support an advertised feature. This one is correct.</span><span class="style1">WHAT'S NEW IN VERSION 4.0</span><span class="style2">ΓÇó New XCMD's include: DelimitedChunk, RandOrder, DeleteRes, PrintPictRes, FileToPictRes, CompareStrings, GetFieldText, SetFieldText, DisposeFieldText, TDWindow, Clipboard, ReplaceChar,BinaryFile, LastVisibleChar, EditWindow, Clipboard, and ListWindow.ΓÇó We have marked each XCMD to indicate its compatibility with HyperCard versions 1 and 2 and with SuperCard. We consider HyperCard 1.2.5, HyperCard 2.1, and SuperCard 1.6 to be the mature versions in each case. The mark is a field at the top left of each documentation card that contains the text "</span><span class="style1">HC1 HC2 SC". </span><span class="style2">Gray text indicates incompatibility. In the case of XCMD's that are not compatible with HyperCard version 2, we really mean that the XCMD will work with that version but provides a function that is provided by HyperCard 2.1 itself.ΓÇó There are revisions to ModalDialog, SerialHandler and version updates to many others.ΓÇó The AuxWindow XCMD hase been removed because it was just an experiment that is rendered obsolete by the external window support added in HyperCard version 2.0.WHAT'S NEW IN RELEASE (3.4.3)A fix to a bug in XScrollBox and XScrollBoxF.WHAT'S NEW IN RELEASE (3.4.2)Version 3.4.2 has two bug fixes: in the XScrollBox set,and in Replace. Also, there is a new variation of XScrollBox called XScrollBoxML.WHAT'S NEW IN RELEASE (3.4.1)Version 3.4.1 contains no new XCMD's since version 3.4, just some bug fixes and enhancements. Bugs were fixed in MenuHandler, the XScrollBox set, and WritePermission. Enhancements were made to the XScrollBox, XScrollBoxF, XScrollBoxM, SortField, SortFieldByItem, and MultiSort.WHAT'S NEW IN RELEASE (3.4)ΓÇó Several of our XCMD's have been altered for compatibility with SuperCard. In particular, Password, GetResources, and each of the three XScrollBox XFCN's have undergone minor revisions for that purpose. We have chosen not to fix the incompatibilities of two of our XCMD's, MenuHandler and AuxWindow, because they are not useful in SuperCard's environment. The remainder of the XCMD's in this stack have passed our SuperCard compatibility tests without revision; however, those which manipulate resources or return information about resources, ClipToPICT, PICTFileToRes, DeleteResFork, IsResource, GetResources, RInstall, and ResList, are seldom appropriate for use with SuperCard, which substitutes routines and data structures of its own for traditional Macintosh resource management.ΓÇó The TextStream XCMD was rewritten. A number of bugs have been fixed, and the source is now more presentable.ΓÇó Minor bugs have been fixed in several of the XCMD's. Their changes have been documented under the heading "Revision History" on the cards that describe them. Bugs have been fixed in PictureShow, ClipToPICT, PICTFileToRes, DeleteResFork, RInstall, IsResource, ResList, GetResources, ModalDialog, System Folder, HyperFolder, SerialHandler, MenuHandler, XScrollBox, XScrollBoxF, and XScrollBoxM.ΓÇó Some copyright notices have been changed.ΓÇó A few new C utilities have been added to LSC Utilities, now called HC Utilities.ΓÇó There are four new XCMD's: WritePermission, MultiSort, ChooserName, and PopList.ΓÇó Some notes regarding the XCMD's in this stack that were written in THINK CΓäó: All of Roger's XCMD's in release 3.1 were compiled under THINK LightSpeed CΓäó version 3.0. All of the XCMD's that he updated for this release (3.4) were compiled under THINK CΓäó version 4.0. The new MultiSort XCMD compiles under THINK CΓäó 4.0 but uses the "qsort" function from THINK LightSpeed CΓäó 3.0.ΓÇó In our scripts, we've made a greater overall effort to show off our own stuff. We've provided examples on most of the cards that describe our XCMD's, and the script of this stack is replete with instances of their use.ΓÇó The source code for almost all of the XCMD's is now available in this stack, including several for which source was not available in earlier releases. (There is one XFCN whose source we included in earlier releases but not in this release, Roger Brown's SerialHandler. It should be noted that the source to SerialHandler we've previously released will compile under THINK's LightspeedC 3.0, but it won't produce a working XCMD. Under LightspeedC 2.15, it produces a working though somewhat imperfect SerialHandler.)CHANGES IN VERSION 3.2 (September 15, 1989):ΓÇó Version 3.2 was a limited internal release. It incorporated two new XCMD's (MultiSort and ChooserName) and some copyright changes.ΓÇó Note: Version 3.2 was erroneously marked 3.3 on the first card and 3.1 in the vers resource. Yes, we released it in a very big hurry. To minimize confusion, there was no version 3.3 release.CHANGES IN VERSION 3.1 (June 1, 1989):ΓÇó Most of the XCMD's and XFCN's that were released in earlier Dartmouth stacks were updated in version 3.1. Several bugs were fixed, and the sources were recompiled using the latest versions of the development systems we use.ΓÇó Two of the previously released XCMD's were rewritten so that frequently requested features could be added: 1) the PopUpPicture XCMD was transformed into a new XCMD, PictureShow, that has all the features of PopUpPicture and can also create a modeless window that's disposed of under script control by another new XCMD, PictureHide. Moreover, PictureShow automatically extracts color table information from pictures in PICT2 format, so that it can display those pictures in their proper colors. 2) the FieldToFile XCMD was replaced by a new XCMD, WriteToFile, that is capable of writing the contents of any HyperTalk container to a file, not just fields, and can append to as well as replace existing files.ΓÇó In all, we released twenty new HyperCard extensions in version 3.1: WriteToFile, PictureShow, PictureHide, ModalDialog, SizeCardWindow, ObjectExists, Password, ConvertDate, SystemFolder, HyperFolder, AuxActive, RInstall, GetResources, IsResource, and ResList from Kevin, and SortField, SortFieldByItem, MenuHandler, FindKey, and Replace from Roger.</span></text>
</content>
<content>
<layer>card</layer>
<id>1</id>
<text>4.0.3EditWindow was not calling the closeFunction if there wre no changes.I forgot to change the vers resource.ModalDialog does not call TEFromScrap when it opens. Also changed the segmentation parameter in it's make script.SerialHandler GetNulls returns "\r" for return characters from the port.EditWindow and ListWIndow have a line to dispose a handle after EvalExpr.GetFieldText card script changed to refresh the demo text.4.0.2ListWindow now has a zoom parameter. It and EditWindow only zoom to the same screen as the card window.ReplaceChar is fixed.The XCMD menu behaves better on suspend and resume.SerialHandler: added BREAK command and fixed erroneouw error message on close.4.0.1ListWindow presentation bug: close the demo window when leave the card. EditWindow did it correctly.Sometimes get confusion in mouseDownInListWIndow if Index is open and demo ListWindow is also open? Can't reproduce.Close Index window when leave stack.SerialHandler PutNulls: 1. script error when used it.2. Freeze in SerialHandler(Putnulls...)I had 2 copies of SerialHandler in the stack! It was calling the wrong one. The freeze was my Kiewit Serial Driver, also a baud rate mismatch when testing to the modem. Also, the version called had no GETNULLS so an error came back. Updated to add a version command and reinstalled the correct one.</text>
</content>
<name>History</name>
<script></script>
</card>
card_4867.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text><span class="style1">ARTMOUTH XCMD'S 4.0.3</span><span class="style2"></span><span class="style1">Kevin Calhoun, Roger Brown, Susan Tenney, and Eric BaumgartnerDartmouth College, Hanover, NHApril 15, 1993Version 4.0.3</span><span class="style2">The latest release of this stack is usually available via ftp on </span><span class="style1">dartvax.dartmouth.edu</span><span class="style2">. It will be in the form of a binhexed self-extracting archive with a name that looks something like </span><span class="style1">DXCMDs_4.0.x.sea.hqx</span><span class="style2"> in directory </span><span class="style1">/pub/mac</span><span class="style2">.This stack contains the first, second, third and fourth sets of HyperCard XCMD's and XFCN's released by the software developers at Dartmouth College. Contributions have been made by the Courseware Development Group, Academic Computing, Community and Family Medicine, and the Program in Medical Information Science. They were originally written for Dartmouth HyperCard projects but we believe they are generally useful.An earlier version of this stack (3.1) won an Honorable Mention in the "Best Development Tool" category of the MacWorld Magazine "SuperStacks" Contest in 1989.You may distribute these XCMD's and XFCN's in your stacks provided that you do not charge any money for them and that you do not remove the original copyright notices. It is possible to obtain a non-exclusive license from Dartmouth College to distribute XCMD's and XFCN's from this stack commercially--see the card "Licensing Information."You may make use of the source code included in this stack for personal programming purposes, but you cannot distribute it commercially.PrintField, TextStream, FileToClip, FileToField, WriteToFile, PictureShow, ClipToPICT, PICTFileToRes, LeafName, DeleteResFork, GetResources, XScrollBoxF, XScrollBoxM, AuxWindow, C Utilities, MultiSort, and ChooserName ©1988-1989 by the Trustees of Dartmouth College. PictureHide, RInstall, IsResource, ResList, SizeCardWindow, ObjectExists, ModalDialog, Password, ConvertDate, SystemFolder, HyperFolder, AuxActive, WritePermission, FindKey, and Replace ©1989 by the Trustees of Dartmouth College.XScrollBox, FindInField, SerialHandler, MenuHandler, SortField, SortFieldByItem, and PopList ©1989 by Digital Medicine, Inc.DelimitedChunk, RandOrder, DeleteRes, PrintPictRes,CompareStrings,GetFieldText, SetFieldText, DisposeFieldText, TDWindow, Clipboard, ReplaceChar, BinaryFile, and LastVisibleChar,EditWindow, ListWindow ©1992 by the Trustees of Dartmouth College.The authors would like to thank the following people for their technical suggestions and support: Jim Matthews, Steve Maker, Steve Maller, Mark Johnson, Edward Shultz, MD and Greg Jorgensen.</span></text>
</content>
<name>About</name>
<script></script>
</card>
card_2858.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<script>on mouseUppush cardvisual zoom opengo to card id 4189end mouseUp</script>
</part>
<part>
<id>48</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>55</left>
<top>214</top>
<right>214</right>
<bottom>240</bottom>
</rect>
<style>rectangle</style>
<showName> <true /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Licensing Information</name>
<script>on mouseDownset the hilite of me to falsewait while the mouse is downset the hilite of me to trueif the mouseLoc is within the rect of me thenpush cardgo to card id 6696end ifend mouseDown</script>
</part>
<part>
<id>49</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>375</left>
<top>102</top>
<right>483</right>
<bottom>120</bottom>
</rect>
<style>opaque</style>
<showName> <true /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>italic</textStyle>
<name>What's New?</name>
<script>on mouseDownset the hilite of me to falsewait while the mouse is downset the hilite of me to trueif the mouseLoc is within the rect of me thenpush cardgo to card "History"end ifend mouseDown</script>
</part>
<part>
<id>50</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>55</left>
<top>183</top>
<right>214</right>
<bottom>208</bottom>
</rect>
<style>rectangle</style>
<showName> <true /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>About the Authors</name>
<script>on mouseDownset the hilite of me to falsewait while the mouse is downset the hilite of me to trueif the mouseLoc is within the rect of me thenpush cardgo to card id 6949end ifend mouseDown</script>
</part>
<part>
<id>51</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>55</left>
<top>246</top>
<right>214</right>
<bottom>271</bottom>
</rect>
<style>rectangle</style>
<showName> <true /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Reporting Bugs</name>
<script>on mouseDownset the hilite of me to falsewait while the mouse is downset the hilite of me to trueif the mouseLoc is within the rect of me thenpush cardgo to card id 18087end ifend mouseDown</script>
</part>
<part>
<id>52</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>55</left>
<top>153</top>
<right>214</right>
<bottom>177</bottom>
</rect>
<style>rectangle</style>
<showName> <true /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>XCMD Index</name>
<script>on mouseDownset the hilite of me to falsewait while the mouse is downset the hilite of me to trueif the mouseLoc is within the rect of me then DoIndexend mouseDown</script>
</part>
<part>
<id>54</id>
<type>field</type>
<visible> <true /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>35</left>
<top>74</top>
<right>229</right>
<bottom>125</bottom>
</rect>
<style>opaque</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Geneva</font>
<textSize>9</textSize>
<textStyle>plain</textStyle>
<textHeight>12</textHeight>
<name></name>
<script></script>
</part>
<part>
<id>56</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>379</left>
<top>130</top>
<right>478</right>
<bottom>149</bottom>
</rect>
<style>opaque</style>
<showName> <true /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>italic</textStyle>
<name>XCMD's Menu</name>
<script>on mouseDownset the hilite of me to falsewait while the mouse is downset the hilite of me to trueif the mouseLoc is within the rect of me thenlock screenshow card field "menu info"show btn "ok"unlock screen with zoom openend ifend mouseDown</script>
</part>
<part>
<id>57</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>211</left>
<top>164</top>
<right>476</right>
<bottom>294</bottom>
</rect>
<style>shadow</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <true /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>left</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<textHeight>16</textHeight>
<name>menu info</name>
<script></script>
</part>
<part>
<id>58</id>
<type>button</type>
<visible> <false /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>418</left>
<top>268</top>
<right>469</right>
<bottom>290</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>OK</name>
<script>on mouseUplock screenhide card field "menu info"hide meunlock screen with zoom closeend mouseUp</script>
</part>
<part>
<id>53</id>
<type>field</type>
<visible> <false /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <true /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <true /> </lockText>
<rect>
<left>18</left>
<top>179</top>
<right>486</right>
<bottom>324</bottom>
</rect>
<style>opaque</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <false /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Geneva</font>
<textSize>10</textSize>
<textStyle>bold</textStyle>
<textHeight>13</textHeight>
<name>obscure buttons</name>
<script></script>
</part>
<part>
<id>61</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>35</left>
<top>74</top>
<right>229</right>
<bottom>125</bottom>
</rect>
<style>transparent</style>
<showName> <false /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>mask1</name>
<script></script>
</part>
<part>
<id>65</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>435</left>
<top>308</top>
<right>465</right>
<bottom>337</bottom>
</rect>
<style>transparent</style>
<showName> <false /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>8964</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Prev</name>
<script>on mouseDownset the hilite of me to truerepeat foreverlock screengo to prev cardunlock screen with visual effect scroll rightif the mouse is up then exit repeatend repeatset the hilite of me to falseend mouseDown</script>
</part>
<part>
<id>70</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>468</left>
<top>306</top>
<right>497</right>
<bottom>336</bottom>
</rect>
<style>transparent</style>
<showName> <false /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>1013</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>Next</name>
<script>on mouseDownset the hilite of me to truerepeat foreverlock screengo to next cardunlock screen with visual effect scroll leftif the mouse is up then exit repeatend repeatset the hilite of me to falseend mouseDown</script>
<text>This stack © 1988-1993 by the Trustees of Dartmouth College. Permisson is hereby granted for its non-commercial use and distribution.</text>
</content>
<content>
<layer>card</layer>
<id>57</id>
<text>Notice that there is a special XCMD's menu in the menu bar. It has commands to help you find XCMD's in this stack, install them in other stacks, print the documentation and source code for them, and create source files.</text>
</content>
<name>@start</name>
<script>on openCardhide card field "obscure buttons"pass openCardend openCardon mouseDownhide card field "obscure buttons"pass mouseDownend mouseDown</script>
</card>
card_8333.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<text>on openCard UpdateXCMDMenuend opencardon openStack set the userModify to true AddMenuend openstackon closestack RemoveMenu if there is a window "Index" then close window "Index" end ifend closestackon suspendStack if there is a window "Index" then hide window "Index" end if if there is a menu "XCMD's" then delete menu "XCMD's" end ifend suspendStackon resumeStack if there is a window "Index" then show window "Index" end if if there is not a menu "XCMD's" then AddMenu end ifend resumeStackon AddMenu global XCMDsMenu put "Index…,Search…,-,Install…,-,Print Documentation…," into itemList put "Print Source…,-,Save Source in File…" after itemList create menu "XCMD's" put itemList into menu "XCMD's" set the menuMsg of menuItem "Index…" of menu "XCMD's" to DoIndex set the menuMsg of menuItem "Search…" of menu "XCMD's" to DoSearch set the menuMsg of menuItem "Install…" of menu "XCMD's" to Install set the menuMsg of menuItem "Print Documentation…" of menu "XCMD's" to DoPrintDoc set the menuMsg of menuItem "Print Source…" of menu "XCMD's" to DoPrintSource set the menuMsg of menuItem "Save Source in File…" of menu "XCMD's" to DoSourceToFile disable menuItem "Print Documentation…" of menu "XCMD's" disable menuItem "Print Source…" of menu "XCMD's" disable menuItem "Save Source in File…" of menu "XCMD's"end AddMenuon RemoveMenu delete menu "XCMD's"end RemoveMenuon DoIndex get the version if it < 2 then DoOldIndex exit DoIndex end if -- this handler requires ListWindow XCMD if there is a window "Index" then show window "Index" else put cd fld "Index" of cd 1 into list sort list put the rect of the card window into r subtract 10 from item 3 of r subtract 10 from item 4 of r put item 3 of r - 140 into item 1 of r put item 4 of r - 195 into item 2 of r ListWindow open,"Index",r,125,18,Chicago,12,false,false,false,true,list show window "Index" end ifend DoIndexon DoOldIndex -- this handler requires XFCN ListDialog global gLastIndexChoice put cd fld "Index" of cd 1 into list sort list if gLastIndexChoice is empty or gLastIndexChoice is "Cancel" then put 1 into gLastIndexChoice end if get ListDialog(gLastIndexChoice,"Choose an XCMD:",list) go to this card -- update the window if it is not empty and it is not "Cancel" then set the cursor to watch put item 1 of it into gLastIndexChoice lock screen if item 2 of it is "picturehide" then -- these two are together put "pictureshow" into item 2 of it end if go card item 2 of it unlock screen with visual effect barn door open set the cursor to hand end if choose browse toolend DoOldIndexon MouseDownInListWindow theWindow global XXLWSelection if the name of window id theWindow is not "Index" then beep exit to HyperCard end if get XXLWSelection delete item 1 to 2 of it visual effect barn door open if it is "pictureHide" then put "PictureShow" into it set the cursor to watch go card itend MouseDownInListWIndowon DoSearch -- this handler requires the following resources: -- DLOG "Find",DITL "Find",XFCN "ModalDialog" global findMode,whatToFind put whatToFind into line 4 of dialogInput if findMode is "whole" then put "ON" into line 5 of dialogInput else if findMode is "string" then put "ON" into line 6 of dialogInput else put "ON" into line 7 of dialogInput put ModalDialog("find",dialogInput,cardCenter) into dialogOutput if dialogOutput is "Cancel" then exit DoSearch if line 4 of dialogOutput is empty then exit DoSearch put line 4 of dialogOutput into whatToFind if line 5 of dialogOutput is "ON" then put "whole" into findMode else if line 6 of dialogOutput is "ON" then put "string" into findMode else put empty into findMode put "find" && findMode && quote & whatToFind & quote into command go next do commandend DoSearchon DoPrintDoc if there is a card field "Documentation" then print card field "Documentation" else if there is a field "Documentation" then print field "Documentation" end ifend DoPrintDocon DoPrintSource if there is a cd fld "source" then print cd fld "source" if there is a cd fld "more source" then print cd fld "more source" end if else if fld "Source" is not empty then print fld "Source" end if if fld "More Source" is not empty then print fld "More Source" end if end if if there is a cd fld "ProtoTypes" then print cd fld "ProtoTypes" end ifend DoPrintSourceon ShowError theError answer "Sorry, an error occurred. (" & theError & ")"end ShowErroron DoSourceToFile -- this handler requires XCMD WriteToFile put the short name of this card into fileName if there is a cd fld "documentation" then get line 2 of cd fld "documentation" else get line 2 of fld "documentation" end if if "Kevin" is not in it then put ".c" after fileName put "KAHL" into creator else put ".p" after fileName put "MPS " into creator end if if there is a cd field "source" then WriteToFile cd field "Source",FALSE,fileName,FALSE,creator put the result into theResult if word 1 of theResult is "Error" then ShowError -- the sources to some are in two parts,therefore the following: if there is a cd field "more source" then WriteToFile field "More Source",TRUE,theResult,TRUE end if else if field "source" is not empty then WriteToFile field "Source",FALSE,fileName,FALSE,creator put the result into theResult if word 1 of theResult is "Error" then ShowError end if -- the sources to some are in two parts,therefore the following: if field "more source" is not empty then WriteToFile field "More Source",TRUE,theResult,TRUE end if end if if there is a cd field "prototypes" then put the short name of this card into fileName put ".h" after fileName WriteToFile cd field "Prototypes",FALSE,fileName,FALSE,creator put the result into theResult if word 1 of theResult is "Error" then ShowError end ifend DoSourceToFileon UpdateXCMDMenu if "@" is not in the short name of this card then enable menuItem "Print Documentation…" of menu "XCMD's" else disable menuItem "Print Documentation…" of menu "XCMD's" end if put false into update if there is a fld "source" then if field "source" is not empty then put true into update end if end if if there is a cd fld "source" then if cd field "source" is not empty then put true into update end if end if if update then enable menuItem "Print Source…" of menu "XCMD's" enable menuItem "Save Source in File…" of menu "XCMD's" else disable menuItem "Print Source…" of menu "XCMD's" disable menuItem "Save Source in File…" of menu "XCMD's" end if get empty if there is a cd fld "documentation" then get cd field "documentation" else if there is a fld "documentation" then get fld "documentation" end if get second word of first line of it if it is "XFCN" or it is "XCMD" then enable menuItem "Install…" of menu "XCMD's" else disable menuItem "Install…" of menu "XCMD's" end ifend UpdateXCMDMenufunction ResInStack resType,resName,resID,stackName global resInfo lock screen push card go to stack stackName put the long name of this stack into stackPathname delete word 1 of stackPathname delete char 1 of stackPathname delete last char of stackPathName put IsResource(resType,resName,resID,TRUE) into resExists pop card unlock screen if resExists is FALSE then return FALSE else return (item 5 of resInfo is stackPathname)end ResInStackon InstallResource resType,resName,targetStack global resInfo set cursor to watch if not IsResource(resType,resName) THEN answer resType && quote & resName & quote && "does not exist." exit InstallResource end if put item 3 of resInfo into resID put the long name of this stack into thisStack delete first word of thisStack delete first char of thisStack delete last char of thisStack if targetStack is thisStack then exit InstallResource set lockMessages to TRUE lock screen push card go stack targetStack if ResInStack(resType,resName,empty,targetStack) then answer "Replace" && resType && quote & resName & quote & "?"¬ with "OK" or "Cancel" if it is "Cancel" then pop card unlock screen set lockMessages to FALSE exit InstallResource end if end if if ResInStack(resType,empty,resID,targetStack) then if item 2 of resInfo is not resName then answer "Replace" && resType && resID & "?"¬ with "OK" or "Cancel" if it is "Cancel" then pop card unlock screen set lockMessages to FALSE exit InstallResource end if end if end if pop card RInstall resType,resName,targetStack get the result if it is not empty then answer it unlock screen set lockMessages to FALSEend InstallResourcefunction ChooseTargetStack set lockMessages to TRUE lock screen push card put the short name of this card into resName if LENGTH(resName) > 14 then put "resource" into resName go stack "target stack for" && resName put the long name of this stack into targetStack delete first word of targetStack delete first char of targetStack delete last char of targetStack pop card unlock screen set lockMessages to FALSE return targetStackend ChooseTargetStackon lockFields lockOrUnlock set lockMessages to true put the number of bgs into bNum repeat with b = 1 to bNum put "background"&&b go bg b put the number of fields into fNum repeat with f = 1 to fNum put the name of field f into fname set the lockText of fname to lockOrUnlock end repeat end repeat go first put the number of cards into cNum repeat with c = 1 to cNum put "card"&&c go card c put the number of card fields into fNum repeat with f = 1 to fNum put the id of card field f into fID set the locktext of card field ID fID to lockOrUnlock end repeat end repeat go first set lockMessages to false hide msgend lockFieldson FindUnlockedFields set lockMessages to true put the number of bgs into bNum put the id of this card into saveid go next repeat while the id of this card is not saveID put the number of fields into fNum repeat with f = 1 to fNum put the short name of field f into fname if the lockText of fld fname is false then answer fName exit to HyperCard end if end repeat put the number of card fields into fNum repeat with f = 1 to fNum put the id of card field f into fID if the lockText of cd fld id fID is false then answer the short name of cd fld id fID exit to HyperCard end if end repeat go next end repeat set lockMessages to false hide msgend FindUnlockedFieldson SetProtect lockOrUnlock set lockMessages to true put the number of bgs into bNum repeat with b = 1 to bNum put "background"&&b go bg b set cantDelete of this bg to lockOrUnlock end repeat go first put the number of cards into cNum repeat with c = 1 to cNum put "card"&&c go card c set cantDelete of this card to lockOrUnlock end repeat go first set lockMessages to false hide msgend SetProtecton printNames put empty into x lock screen set the lockMessages to true repeat with i = 1 to the number of cards go card i put the short name of this card & return after x end repeat print xend printNames-- Notes:-- 1. Bug fix notes are in a hidden field called notes on-- card "History".-- 2. To make the gray text used in the title:-- On white space, type letters in Times bold (20 for the date, 36 for the title).-- Lasso it and drag onto black space.-- Invert that to make white letters on black.-- Return to the original and fill each letter with gray using the bucket.-- Lasso that and drag to the white on black copy.-- Position right and down 1 pixel.</text>
</content>
<name>ss</name>
<script></script>
</card>
card_9912.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE card PUBLIC "-//Apple, Inc.//DTD card V 2.0//EN" "" >
<script>on mouseUplock screenhide card field "menu info"hide meunlock screen with zoom closeend mouseUp</script>
</part>
<part>
<id>74</id>
<type>field</type>
<visible> <true /> </visible>
<dontWrap> <false /> </dontWrap>
<dontSearch> <false /> </dontSearch>
<sharedText> <false /> </sharedText>
<fixedLineHeight> <false /> </fixedLineHeight>
<autoTab> <false /> </autoTab>
<lockText> <false /> </lockText>
<rect>
<left>102</left>
<top>120</top>
<right>399</right>
<bottom>201</bottom>
</rect>
<style>rectangle</style>
<autoSelect> <false /> </autoSelect>
<showLines> <false /> </showLines>
<wideMargins> <true /> </wideMargins>
<multipleLines> <false /> </multipleLines>
<reservedFamily> 0 </reservedFamily>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Geneva</font>
<textSize>10</textSize>
<textStyle>plain</textStyle>
<textHeight>13</textHeight>
<name></name>
<script></script>
</part>
<part>
<id>75</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>104</left>
<top>122</top>
<right>397</right>
<bottom>199</bottom>
</rect>
<style>transparent</style>
<showName> <false /> </showName>
<highlight> <true /> </highlight>
<autoHighlight> <false /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Chicago</font>
<textSize>12</textSize>
<textStyle>plain</textStyle>
<name>cover</name>
<script></script>
</part>
<part>
<id>76</id>
<type>button</type>
<visible> <true /> </visible>
<reserved5> 0 </reserved5>
<reserved4> 0 </reserved4>
<reserved3> 0 </reserved3>
<reserved2> 0 </reserved2>
<reserved1> 0 </reserved1>
<enabled> <true /> </enabled>
<rect>
<left>170</left>
<top>238</top>
<right>329</right>
<bottom>278</bottom>
</rect>
<style>roundrect</style>
<showName> <true /> </showName>
<highlight> <false /> </highlight>
<autoHighlight> <true /> </autoHighlight>
<sharedHighlight> <true /> </sharedHighlight>
<family>0</family>
<titleWidth>0</titleWidth>
<icon>0</icon>
<textAlign>center</textAlign>
<font>Times</font>
<textSize>30</textSize>
<textStyle>bold</textStyle>
<name>Update</name>
<script>on mouseUpUpdateend mouseUpon Updateanswer "Did you make a copy of your original Dartmouth XCMD stack to be safe?" with "Yes","No"if it is not "Yes" then exit Updateput the short name of this stack into fromStackgo stack "your copy of Darmouth XCMD's" in a new windowif the result is cancel then exit Updateput the short name of this stack into toStackif there is not a cd fld "index" thenanswer "This does not appear to be a DXCMD's stack!" with "Try Anyway","Cancel"if it is "Cancel" thendomenu close stackexit Updateend ifend ifset the cantModify of this stack to falseset the name of card 4 to "History"set the name of card 5 to "Bugs"lock screenset lockmessages to truego stack fromStackrepeat with i = 3 to the number of cardsput "Update card "&i-2&" of "&the number of cards - 2set the cursor to busy-- copy some new cardsgo card idomenu copy cardput the short name of this card into cNamego stack toStackgo card cNameif the result is not empty thenanswer the resultexit Updateend ifdoMenu paste cardset the cantDelete of this card to truego previf the short name of this card is not cName thenanswer "I got mixed up somehow. Sorry!"exit Updateend ifset the cantDelete of this card to falseset the cantDelete of this bg to falsedomenu delete cardset the cantDelete of this bg to truego stack fromStackend repeat-- give it a new stack scriptset the cursor to busyput "Update stack script"go firstget cd fld "ss" of card "ss"go stack toStackset the script of this stack to itput the long name of this stack into rStackdelete word 1 of rStackdelete char 1 of rStackdelete last char of rStackgo stack fromStack-- now move the resourcesput "Update resources"set the cursor to busyset lockmessages to falseRInstall XCMD,ListWindow,rStackCheckError the Resultset the cursor to busyRInstall XCMD,EditWindow,rStackCheckError the Resultset the cursor to busyRInstall XFCN, SerialHandler,rStackCheckError the Resultset the cursor to busyRInstall XFCN,ModalDialog,rStackCheckError the Resultset the cursor to busyRInstall XFCN,ReplaceChar,rStackCheckError the ResultRInstall vers,"#1",rStackCheckError the Resultput emptyhide msgunlock screenput "Update complete. You might want to change the stack name " into xput "to Dartmouth XCMD's 4.0.3 and compact it." after xanswer xend Updateon CheckError textif text is not empty thenanswer textexit to HyperCardend ifend CheckError</script>
</part>
<content>
<layer>card</layer>
<id>74</id>
<text>This stack will bring your version 4.0, 4.0.1, or 4.0.2 Dartmouth XCMD's up to the current version 4.0.3. Make an extra copy of your original stack in case any errors occur, then click on the Update button. </text>